Replace ctx->Driver.StencilOp/Func/Mask() functions with
[mesa.git] / src / mesa / drivers / dri / i830 / i830_state.c
1 /**************************************************************************
2
3 Copyright 2001 2d3d Inc., Delray Beach, FL
4
5 All Rights Reserved.
6
7 Permission is hereby granted, free of charge, to any person obtaining a
8 copy of this software and associated documentation files (the "Software"),
9 to deal in the Software without restriction, including without limitation
10 on the rights to use, copy, modify, merge, publish, distribute, sub
11 license, and/or sell copies of the Software, and to permit persons to whom
12 the Software is furnished to do so, subject to the following conditions:
13
14 The above copyright notice and this permission notice (including the next
15 paragraph) shall be included in all copies or substantial portions of the
16 Software.
17
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
21 ATI, VA LINUX SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
22 DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
23 OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
24 USE OR OTHER DEALINGS IN THE SOFTWARE.
25
26 **************************************************************************/
27
28 /* $XFree86: xc/lib/GL/mesa/src/drv/i830/i830_state.c,v 1.6 2003/01/28 22:47:06 dawes Exp $ */
29
30 /*
31 * Author:
32 * Jeff Hartmann <jhartmann@2d3d.com>
33 *
34 * Heavily based on the I810 driver, which was written by:
35 * Keith Whitwell <keith@tungstengraphics.com>
36 */
37
38 #include "glheader.h"
39 #include "buffers.h"
40 #include "context.h"
41 #include "macros.h"
42 #include "enums.h"
43 #include "dd.h"
44
45 #include "texmem.h"
46
47 #include "i830_screen.h"
48 #include "i830_dri.h"
49
50 #include "i830_context.h"
51 #include "i830_state.h"
52 #include "i830_tex.h"
53 #include "i830_tris.h"
54 #include "i830_ioctl.h"
55
56 #include "swrast/swrast.h"
57 #include "array_cache/acache.h"
58 #include "tnl/tnl.h"
59 #include "swrast_setup/swrast_setup.h"
60
61 #include "tnl/t_pipeline.h"
62
63 static __inline__ GLuint i830PackColor(GLuint format,
64 GLubyte r, GLubyte g,
65 GLubyte b, GLubyte a)
66 {
67
68 if (I830_DEBUG&DEBUG_DRI)
69 fprintf(stderr, "%s\n", __FUNCTION__);
70
71 switch (format) {
72 case DV_PF_555:
73 return I830PACKCOLOR1555(r,g,b,a);
74 case DV_PF_565:
75 return I830PACKCOLOR565(r,g,b);
76 case DV_PF_8888:
77 return I830PACKCOLOR8888(r,g,b,a);
78 default:
79 fprintf(stderr, "unknown format %d\n", (int)format);
80 return 0;
81 }
82 }
83
84 static void
85 i830StencilFuncSeparate(GLcontext *ctx, GLenum face, GLenum func, GLint ref,
86 GLuint mask)
87 {
88 i830ContextPtr imesa = I830_CONTEXT(ctx);
89 int test = 0;
90
91 mask = mask & 0xff;
92
93 if (I830_DEBUG&DEBUG_DRI)
94 fprintf(stderr, "%s : func: %s, ref : 0x%x, mask: 0x%x\n", __FUNCTION__,
95 _mesa_lookup_enum_by_nr(func), ref, mask);
96
97 switch(func) {
98 case GL_NEVER:
99 test = COMPAREFUNC_NEVER;
100 break;
101 case GL_LESS:
102 test = COMPAREFUNC_LESS;
103 break;
104 case GL_LEQUAL:
105 test = COMPAREFUNC_LEQUAL;
106 break;
107 case GL_GREATER:
108 test = COMPAREFUNC_GREATER;
109 break;
110 case GL_GEQUAL:
111 test = COMPAREFUNC_GEQUAL;
112 break;
113 case GL_NOTEQUAL:
114 test = COMPAREFUNC_NOTEQUAL;
115 break;
116 case GL_EQUAL:
117 test = COMPAREFUNC_EQUAL;
118 break;
119 case GL_ALWAYS:
120 test = COMPAREFUNC_ALWAYS;
121 break;
122 default:
123 return;
124 }
125
126 I830_STATECHANGE(imesa, I830_UPLOAD_CTX);
127 imesa->Setup[I830_CTXREG_STATE4] &= ~MODE4_ENABLE_STENCIL_TEST_MASK;
128 imesa->Setup[I830_CTXREG_STATE4] |= (ENABLE_STENCIL_TEST_MASK |
129 STENCIL_TEST_MASK(mask));
130 imesa->Setup[I830_CTXREG_STENCILTST] &= ~(STENCIL_REF_VALUE_MASK |
131 ENABLE_STENCIL_TEST_FUNC_MASK);
132 imesa->Setup[I830_CTXREG_STENCILTST] |= (ENABLE_STENCIL_REF_VALUE |
133 ENABLE_STENCIL_TEST_FUNC |
134 STENCIL_REF_VALUE(ref) |
135 STENCIL_TEST_FUNC(test));
136 }
137
138 static void
139 i830StencilMaskSeparate(GLcontext *ctx, GLenum face, GLuint mask)
140 {
141 i830ContextPtr imesa = I830_CONTEXT(ctx);
142
143 if (I830_DEBUG&DEBUG_DRI)
144 fprintf(stderr, "%s : mask 0x%x\n", __FUNCTION__, mask);
145
146 mask = mask & 0xff;
147
148 I830_STATECHANGE(imesa, I830_UPLOAD_CTX);
149 imesa->Setup[I830_CTXREG_STATE4] &= ~MODE4_ENABLE_STENCIL_WRITE_MASK;
150 imesa->Setup[I830_CTXREG_STATE4] |= (ENABLE_STENCIL_WRITE_MASK |
151 STENCIL_WRITE_MASK(mask));
152 }
153
154 static void
155 i830StencilOpSeparate(GLcontext *ctx, GLenum face, GLenum fail, GLenum zfail,
156 GLenum zpass)
157 {
158 i830ContextPtr imesa = I830_CONTEXT(ctx);
159 int fop, dfop, dpop;
160
161 if (I830_DEBUG&DEBUG_DRI)
162 fprintf(stderr, "%s: fail : %s, zfail: %s, zpass : %s\n", __FUNCTION__,
163 _mesa_lookup_enum_by_nr(fail),
164 _mesa_lookup_enum_by_nr(zfail),
165 _mesa_lookup_enum_by_nr(zpass));
166
167 fop = 0; dfop = 0; dpop = 0;
168
169 switch(fail) {
170 case GL_KEEP:
171 fop = STENCILOP_KEEP;
172 break;
173 case GL_ZERO:
174 fop = STENCILOP_ZERO;
175 break;
176 case GL_REPLACE:
177 fop = STENCILOP_REPLACE;
178 break;
179 case GL_INCR:
180 fop = STENCILOP_INCRSAT;
181 break;
182 case GL_DECR:
183 fop = STENCILOP_DECRSAT;
184 break;
185 case GL_INCR_WRAP:
186 fop = STENCILOP_INCR;
187 break;
188 case GL_DECR_WRAP:
189 fop = STENCILOP_DECR;
190 break;
191 case GL_INVERT:
192 fop = STENCILOP_INVERT;
193 break;
194 default:
195 break;
196 }
197 switch(zfail) {
198 case GL_KEEP:
199 dfop = STENCILOP_KEEP;
200 break;
201 case GL_ZERO:
202 dfop = STENCILOP_ZERO;
203 break;
204 case GL_REPLACE:
205 dfop = STENCILOP_REPLACE;
206 break;
207 case GL_INCR:
208 dfop = STENCILOP_INCRSAT;
209 break;
210 case GL_DECR:
211 dfop = STENCILOP_DECRSAT;
212 break;
213 case GL_INCR_WRAP:
214 dfop = STENCILOP_INCR;
215 break;
216 case GL_DECR_WRAP:
217 dfop = STENCILOP_DECR;
218 break;
219 case GL_INVERT:
220 dfop = STENCILOP_INVERT;
221 break;
222 default:
223 break;
224 }
225 switch(zpass) {
226 case GL_KEEP:
227 dpop = STENCILOP_KEEP;
228 break;
229 case GL_ZERO:
230 dpop = STENCILOP_ZERO;
231 break;
232 case GL_REPLACE:
233 dpop = STENCILOP_REPLACE;
234 break;
235 case GL_INCR:
236 dpop = STENCILOP_INCRSAT;
237 break;
238 case GL_DECR:
239 dpop = STENCILOP_DECRSAT;
240 break;
241 case GL_INCR_WRAP:
242 dpop = STENCILOP_INCR;
243 break;
244 case GL_DECR_WRAP:
245 dpop = STENCILOP_DECR;
246 break;
247 case GL_INVERT:
248 dpop = STENCILOP_INVERT;
249 break;
250 default:
251 break;
252 }
253
254
255 I830_STATECHANGE(imesa, I830_UPLOAD_CTX);
256 imesa->Setup[I830_CTXREG_STENCILTST] &= ~(STENCIL_OPS_MASK);
257 imesa->Setup[I830_CTXREG_STENCILTST] |= (ENABLE_STENCIL_PARMS |
258 STENCIL_FAIL_OP(fop) |
259 STENCIL_PASS_DEPTH_FAIL_OP(dfop) |
260 STENCIL_PASS_DEPTH_PASS_OP(dpop));
261 }
262
263 static void i830AlphaFunc(GLcontext *ctx, GLenum func, GLfloat ref)
264 {
265 i830ContextPtr imesa = I830_CONTEXT(ctx);
266 int test = 0;
267 GLuint refByte = (GLint) (ref * 255.0);
268
269 switch(func) {
270 case GL_NEVER:
271 test = COMPAREFUNC_NEVER;
272 break;
273 case GL_LESS:
274 test = COMPAREFUNC_LESS;
275 break;
276 case GL_LEQUAL:
277 test = COMPAREFUNC_LEQUAL;
278 break;
279 case GL_GREATER:
280 test = COMPAREFUNC_GREATER;
281 break;
282 case GL_GEQUAL:
283 test = COMPAREFUNC_GEQUAL;
284 break;
285 case GL_NOTEQUAL:
286 test = COMPAREFUNC_NOTEQUAL;
287 break;
288 case GL_EQUAL:
289 test = COMPAREFUNC_EQUAL;
290 break;
291 case GL_ALWAYS:
292 test = COMPAREFUNC_ALWAYS;
293 break;
294 default:
295 return;
296 }
297
298 I830_STATECHANGE(imesa, I830_UPLOAD_CTX);
299 imesa->Setup[I830_CTXREG_STATE2] &= ~ALPHA_TEST_REF_MASK;
300 imesa->Setup[I830_CTXREG_STATE2] |= (ENABLE_ALPHA_TEST_FUNC |
301 ENABLE_ALPHA_REF_VALUE |
302 ALPHA_TEST_FUNC(test) |
303 ALPHA_REF_VALUE(refByte));
304 }
305
306 /* This function makes sure that the proper enables are
307 * set for LogicOp, Independant Alpha Blend, and Blending.
308 * It needs to be called from numerous places where we
309 * could change the LogicOp or Independant Alpha Blend without subsequent
310 * calls to glEnable.
311 */
312 static void i830EvalLogicOpBlendState(GLcontext *ctx)
313 {
314 i830ContextPtr imesa = I830_CONTEXT(ctx);
315
316 I830_STATECHANGE(imesa, I830_UPLOAD_CTX);
317
318 imesa->Setup[I830_CTXREG_ENABLES_1] &= ~(ENABLE_COLOR_BLEND |
319 ENABLE_LOGIC_OP_MASK);
320 imesa->Setup[I830_CTXREG_IALPHAB] &= ~ENABLE_INDPT_ALPHA_BLEND;
321
322 if (ctx->Color.ColorLogicOpEnabled) {
323 imesa->Setup[I830_CTXREG_ENABLES_1] |= (DISABLE_COLOR_BLEND |
324 ENABLE_LOGIC_OP);
325 imesa->Setup[I830_CTXREG_IALPHAB] |= DISABLE_INDPT_ALPHA_BLEND;
326 } else if (ctx->Color.BlendEnabled) {
327 imesa->Setup[I830_CTXREG_ENABLES_1] |= (ENABLE_COLOR_BLEND |
328 DISABLE_LOGIC_OP);
329
330 /* If the alpha blend state does not match the color blend state,
331 * enable independent alpha blending. Otherwise, leave it disabled
332 * and the hardware will use the color blend state for both.
333 */
334
335 if ( 0 && (imesa->Setup[I830_CTXREG_IALPHAB] & BLEND_STATE_MASK)
336 != (imesa->Setup[I830_CTXREG_STATE1] & BLEND_STATE_MASK) ) {
337 imesa->Setup[I830_CTXREG_IALPHAB] |= ENABLE_INDPT_ALPHA_BLEND;
338 } else {
339 imesa->Setup[I830_CTXREG_IALPHAB] |= DISABLE_INDPT_ALPHA_BLEND;
340 }
341 } else {
342 imesa->Setup[I830_CTXREG_ENABLES_1] |= (DISABLE_COLOR_BLEND |
343 DISABLE_LOGIC_OP);
344 imesa->Setup[I830_CTXREG_IALPHAB] |= DISABLE_INDPT_ALPHA_BLEND;
345 }
346 }
347
348 static void i830BlendColor(GLcontext *ctx, const GLfloat color[4])
349 {
350 i830ContextPtr imesa = I830_CONTEXT(ctx);
351 GLubyte r, g, b, a;
352
353 if (I830_DEBUG&DEBUG_DRI)
354 fprintf(stderr, "%s\n", __FUNCTION__);
355
356 FLOAT_COLOR_TO_UBYTE_COLOR(r, color[RCOMP]);
357 FLOAT_COLOR_TO_UBYTE_COLOR(g, color[GCOMP]);
358 FLOAT_COLOR_TO_UBYTE_COLOR(b, color[BCOMP]);
359 FLOAT_COLOR_TO_UBYTE_COLOR(a, color[ACOMP]);
360
361 I830_STATECHANGE(imesa, I830_UPLOAD_CTX);
362 imesa->Setup[I830_CTXREG_BLENDCOLR] = ((a << 24) |
363 (r << 16) |
364 (g << 8) |
365 b);
366 }
367
368 /**
369 * Calculate the hardware blend factor setting. This same function is used
370 * for source and destination of both alpha and RGB.
371 *
372 * \returns
373 * The hardware register value for the specified blend factor. This value
374 * will need to be shifted into the correct position for either source or
375 * destination factor.
376 *
377 * \todo
378 * Since the two cases where source and destination are handled differently
379 * are essentially error cases, they should never happen. Determine if these
380 * cases can be removed.
381 */
382 static int blend_factor( GLenum factor, GLboolean is_src )
383 {
384 int func;
385
386 switch( factor ) {
387 case GL_ZERO:
388 func = BLENDFACT_ZERO;
389 break;
390 case GL_ONE:
391 func = BLENDFACT_ONE;
392 break;
393 case GL_SRC_COLOR:
394 func = BLENDFACT_SRC_COLR;
395 break;
396 case GL_ONE_MINUS_SRC_COLOR:
397 func = BLENDFACT_INV_SRC_COLR;
398 break;
399 case GL_SRC_ALPHA:
400 func = BLENDFACT_SRC_ALPHA;
401 break;
402 case GL_ONE_MINUS_SRC_ALPHA:
403 func = BLENDFACT_INV_SRC_ALPHA;
404 break;
405 case GL_DST_ALPHA:
406 func = BLENDFACT_DST_ALPHA;
407 break;
408 case GL_ONE_MINUS_DST_ALPHA:
409 func = BLENDFACT_INV_DST_ALPHA;
410 break;
411 case GL_DST_COLOR:
412 func = BLENDFACT_DST_COLR;
413 break;
414 case GL_ONE_MINUS_DST_COLOR:
415 func = BLENDFACT_INV_DST_COLR;
416 break;
417 case GL_SRC_ALPHA_SATURATE:
418 func = (is_src) ? BLENDFACT_SRC_ALPHA_SATURATE : BLENDFACT_ZERO;
419 break;
420 case GL_CONSTANT_COLOR:
421 func = BLENDFACT_CONST_COLOR;
422 break;
423 case GL_ONE_MINUS_CONSTANT_COLOR:
424 func = BLENDFACT_INV_CONST_COLOR;
425 break;
426 case GL_CONSTANT_ALPHA:
427 func = BLENDFACT_CONST_ALPHA;
428 break;
429 case GL_ONE_MINUS_CONSTANT_ALPHA:
430 func = BLENDFACT_INV_CONST_ALPHA;
431 break;
432 default:
433 func = (is_src) ? BLENDFACT_ONE : BLENDFACT_ZERO;
434 }
435
436 return func;
437 }
438
439
440 /**
441 * Sets both the blend equation (called "function" in i830 docs) and the
442 * blend function (called "factor" in i830 docs). This is done in a single
443 * function because some blend equations (i.e., \c GL_MIN and \c GL_MAX)
444 * change the interpretation of the blend function.
445 */
446
447 static void i830_set_blend_state( GLcontext * ctx )
448 {
449 i830ContextPtr imesa = I830_CONTEXT(ctx);
450 int funcA;
451 int funcRGB;
452 int eqnA;
453 int eqnRGB;
454
455
456 funcRGB = SRC_BLND_FACT( blend_factor( ctx->Color.BlendSrcRGB, GL_TRUE ) )
457 | DST_BLND_FACT( blend_factor( ctx->Color.BlendDstRGB, GL_FALSE ) );
458
459 switch(ctx->Color.BlendEquationRGB) {
460 case GL_FUNC_ADD:
461 eqnRGB = BLENDFUNC_ADD;
462 break;
463 case GL_MIN:
464 eqnRGB = BLENDFUNC_MIN;
465 funcRGB = SRC_BLND_FACT(BLENDFACT_ONE) | DST_BLND_FACT(BLENDFACT_ONE);
466 break;
467 case GL_MAX:
468 eqnRGB = BLENDFUNC_MAX;
469 funcRGB = SRC_BLND_FACT(BLENDFACT_ONE) | DST_BLND_FACT(BLENDFACT_ONE);
470 break;
471 case GL_FUNC_SUBTRACT:
472 eqnRGB = BLENDFUNC_SUB;
473 break;
474 case GL_FUNC_REVERSE_SUBTRACT:
475 eqnRGB = BLENDFUNC_RVRSE_SUB;
476 break;
477 default:
478 fprintf( stderr, "[%s:%u] Invalid RGB blend equation (0x%04x).\n",
479 __func__, __LINE__, ctx->Color.BlendEquationRGB );
480 return;
481 }
482
483
484 funcA = SRC_ABLEND_FACT( blend_factor( ctx->Color.BlendSrcA, GL_TRUE ) )
485 | DST_ABLEND_FACT( blend_factor( ctx->Color.BlendDstA, GL_FALSE ) );
486
487 switch(ctx->Color.BlendEquationA) {
488 case GL_FUNC_ADD:
489 eqnA = BLENDFUNC_ADD;
490 break;
491 case GL_MIN:
492 eqnA = BLENDFUNC_MIN;
493 funcA = SRC_BLND_FACT(BLENDFACT_ONE) | DST_BLND_FACT(BLENDFACT_ONE);
494 break;
495 case GL_MAX:
496 eqnA = BLENDFUNC_MAX;
497 funcA = SRC_BLND_FACT(BLENDFACT_ONE) | DST_BLND_FACT(BLENDFACT_ONE);
498 break;
499 case GL_FUNC_SUBTRACT:
500 eqnA = BLENDFUNC_SUB;
501 break;
502 case GL_FUNC_REVERSE_SUBTRACT:
503 eqnA = BLENDFUNC_RVRSE_SUB;
504 break;
505 default:
506 fprintf( stderr, "[%s:%u] Invalid alpha blend equation (0x%04x).\n",
507 __func__, __LINE__, ctx->Color.BlendEquationA );
508 return;
509 }
510
511 I830_STATECHANGE(imesa, I830_UPLOAD_CTX);
512
513 imesa->Setup[I830_CTXREG_STATE1] = eqnRGB | funcRGB
514 | STATE3D_MODES_1_CMD
515 | ENABLE_SRC_BLND_FACTOR | ENABLE_DST_BLND_FACTOR
516 | ENABLE_COLR_BLND_FUNC;
517
518 imesa->Setup[I830_CTXREG_IALPHAB] = eqnA | funcA
519 | STATE3D_INDPT_ALPHA_BLEND_CMD
520 | ENABLE_SRC_ABLEND_FACTOR | ENABLE_DST_ABLEND_FACTOR
521 | ENABLE_ALPHA_BLENDFUNC;
522
523
524 /* This will catch a logicop blend equation. It will also ensure
525 * independant alpha blend is really in the correct state (either enabled
526 * or disabled) if blending is already enabled.
527 */
528
529 i830EvalLogicOpBlendState(ctx);
530
531 if (0) {
532 fprintf(stderr, "[%s:%u] STATE1: 0x%08x IALPHAB: 0x%08x blend is %sabled\n",
533 __func__, __LINE__,
534 imesa->Setup[I830_CTXREG_STATE1],
535 imesa->Setup[I830_CTXREG_IALPHAB],
536 (ctx->Color.BlendEnabled) ? "en" : "dis");
537 }
538 }
539
540 static void i830BlendEquationSeparate(GLcontext *ctx,
541 GLenum modeRGB, GLenum modeA)
542 {
543 if (I830_DEBUG&DEBUG_DRI)
544 fprintf(stderr, "%s -> %s, %s\n", __FUNCTION__,
545 _mesa_lookup_enum_by_nr(modeRGB),
546 _mesa_lookup_enum_by_nr(modeA));
547
548 (void) modeRGB;
549 (void) modeA;
550 i830_set_blend_state( ctx );
551 }
552
553
554
555 static void i830BlendFuncSeparate(GLcontext *ctx, GLenum sfactorRGB,
556 GLenum dfactorRGB, GLenum sfactorA,
557 GLenum dfactorA )
558 {
559 if (I830_DEBUG&DEBUG_DRI)
560 fprintf(stderr, "%s -> RGB(%s, %s) A(%s, %s)\n", __FUNCTION__,
561 _mesa_lookup_enum_by_nr(sfactorRGB),
562 _mesa_lookup_enum_by_nr(dfactorRGB),
563 _mesa_lookup_enum_by_nr(sfactorA),
564 _mesa_lookup_enum_by_nr(dfactorA));
565
566 (void) sfactorRGB;
567 (void) dfactorRGB;
568 (void) sfactorA;
569 (void) dfactorA;
570 i830_set_blend_state( ctx );
571 }
572
573 static void i830DepthFunc(GLcontext *ctx, GLenum func)
574 {
575 i830ContextPtr imesa = I830_CONTEXT(ctx);
576 int test = 0;
577
578 if (I830_DEBUG&DEBUG_DRI)
579 fprintf(stderr, "%s\n", __FUNCTION__);
580
581 switch(func) {
582 case GL_NEVER:
583 test = COMPAREFUNC_NEVER;
584 break;
585 case GL_LESS:
586 test = COMPAREFUNC_LESS;
587 break;
588 case GL_LEQUAL:
589 test = COMPAREFUNC_LEQUAL;
590 break;
591 case GL_GREATER:
592 test = COMPAREFUNC_GREATER;
593 break;
594 case GL_GEQUAL:
595 test = COMPAREFUNC_GEQUAL;
596 break;
597 case GL_NOTEQUAL:
598 test = COMPAREFUNC_NOTEQUAL;
599 break;
600 case GL_EQUAL:
601 test = COMPAREFUNC_EQUAL;
602 break;
603 case GL_ALWAYS:
604 test = COMPAREFUNC_ALWAYS;
605 break;
606 default: return;
607 }
608
609 I830_STATECHANGE(imesa, I830_UPLOAD_CTX);
610 imesa->Setup[I830_CTXREG_STATE3] &= ~DEPTH_TEST_FUNC_MASK;
611 imesa->Setup[I830_CTXREG_STATE3] |= (ENABLE_DEPTH_TEST_FUNC |
612 DEPTH_TEST_FUNC(test));
613 }
614
615 static void i830DepthMask(GLcontext *ctx, GLboolean flag)
616 {
617 i830ContextPtr imesa = I830_CONTEXT(ctx);
618
619 if (I830_DEBUG&DEBUG_DRI)
620 fprintf(stderr, "%s flag (%d)\n", __FUNCTION__, flag);
621
622 I830_STATECHANGE(imesa, I830_UPLOAD_CTX);
623
624 imesa->Setup[I830_CTXREG_ENABLES_2] &= ~ENABLE_DIS_DEPTH_WRITE_MASK;
625
626 if (flag && ctx->Depth.Test)
627 imesa->Setup[I830_CTXREG_ENABLES_2] |= ENABLE_DEPTH_WRITE;
628 else
629 imesa->Setup[I830_CTXREG_ENABLES_2] |= DISABLE_DEPTH_WRITE;
630 }
631
632 /* =============================================================
633 * Polygon stipple
634 *
635 * The i830 supports a 4x4 stipple natively, GL wants 32x32.
636 * Fortunately stipple is usually a repeating pattern.
637 */
638 static void i830PolygonStipple( GLcontext *ctx, const GLubyte *mask )
639 {
640 i830ContextPtr imesa = I830_CONTEXT(ctx);
641 const GLubyte *m = mask;
642 GLubyte p[4];
643 int i,j,k;
644 int active = (ctx->Polygon.StippleFlag &&
645 imesa->reduced_primitive == GL_TRIANGLES);
646 GLuint newMask;
647
648 if (active) {
649 I830_STATECHANGE(imesa, I830_UPLOAD_STIPPLE);
650 imesa->StippleSetup[I830_STPREG_ST1] &= ~ST1_ENABLE;
651 }
652
653 p[0] = mask[12] & 0xf; p[0] |= p[0] << 4;
654 p[1] = mask[8] & 0xf; p[1] |= p[1] << 4;
655 p[2] = mask[4] & 0xf; p[2] |= p[2] << 4;
656 p[3] = mask[0] & 0xf; p[3] |= p[3] << 4;
657
658 for (k = 0 ; k < 8 ; k++)
659 for (j = 3 ; j >= 0; j--)
660 for (i = 0 ; i < 4 ; i++, m++)
661 if (*m != p[j]) {
662 imesa->hw_stipple = 0;
663 return;
664 }
665
666 newMask = (((p[0] & 0xf) << 0) |
667 ((p[1] & 0xf) << 4) |
668 ((p[2] & 0xf) << 8) |
669 ((p[3] & 0xf) << 12));
670
671
672 if (newMask == 0xffff || newMask == 0x0) {
673 /* this is needed to make conform pass */
674 imesa->hw_stipple = 0;
675 return;
676 }
677
678 imesa->StippleSetup[I830_STPREG_ST1] &= ~0xffff;
679 imesa->StippleSetup[I830_STPREG_ST1] |= newMask;
680 imesa->hw_stipple = 1;
681
682 if (active)
683 imesa->StippleSetup[I830_STPREG_ST1] |= ST1_ENABLE;
684 }
685
686 static void i830PolygonStippleFallback( GLcontext *ctx, const GLubyte *mask )
687 {
688 i830ContextPtr imesa = I830_CONTEXT(ctx);
689 imesa->hw_stipple = 0;
690 (void) i830PolygonStipple;
691 }
692
693 /* =============================================================
694 * Hardware clipping
695 */
696 static void i830Scissor(GLcontext *ctx, GLint x, GLint y,
697 GLsizei w, GLsizei h)
698 {
699 i830ContextPtr imesa = I830_CONTEXT(ctx);
700 int x1 = x;
701 int y1 = imesa->driDrawable->h - (y + h);
702 int x2 = x + w - 1;
703 int y2 = y1 + h - 1;
704
705 if (I830_DEBUG&DEBUG_DRI)
706 fprintf(stderr, "[%s] x(%d) y(%d) w(%d) h(%d)\n", __FUNCTION__,
707 x, y, w, h);
708
709 if (x1 < 0) x1 = 0;
710 if (y1 < 0) y1 = 0;
711 if (x2 < 0) x2 = 0;
712 if (y2 < 0) y2 = 0;
713
714 if (x2 >= imesa->i830Screen->width) x2 = imesa->i830Screen->width-1;
715 if (y2 >= imesa->i830Screen->height) y2 = imesa->i830Screen->height-1;
716 if (x1 >= imesa->i830Screen->width) x1 = imesa->i830Screen->width-1;
717 if (y1 >= imesa->i830Screen->height) y1 = imesa->i830Screen->height-1;
718
719
720 I830_STATECHANGE(imesa, I830_UPLOAD_BUFFERS);
721 imesa->BufferSetup[I830_DESTREG_SR1] = (y1 << 16) | (x1 & 0xffff);
722 imesa->BufferSetup[I830_DESTREG_SR2] = (y2 << 16) | (x2 & 0xffff);
723 }
724
725 static void i830LogicOp(GLcontext *ctx, GLenum opcode)
726 {
727 i830ContextPtr imesa = I830_CONTEXT(ctx);
728 int tmp = 0;
729
730 if (I830_DEBUG&DEBUG_DRI)
731 fprintf(stderr, "%s\n", __FUNCTION__);
732
733 /* FIXME: This should be a look-up table, like the r200 driver. */
734 switch(opcode) {
735 case GL_CLEAR:
736 tmp = LOGICOP_CLEAR;
737 break;
738 case GL_AND:
739 tmp = LOGICOP_AND;
740 break;
741 case GL_AND_REVERSE:
742 tmp = LOGICOP_AND_RVRSE;
743 break;
744 case GL_COPY:
745 tmp = LOGICOP_COPY;
746 break;
747 case GL_COPY_INVERTED:
748 tmp = LOGICOP_COPY_INV;
749 break;
750 case GL_AND_INVERTED:
751 tmp = LOGICOP_AND_INV;
752 break;
753 case GL_NOOP:
754 tmp = LOGICOP_NOOP;
755 break;
756 case GL_XOR:
757 tmp = LOGICOP_XOR;
758 break;
759 case GL_OR:
760 tmp = LOGICOP_OR;
761 break;
762 case GL_OR_INVERTED:
763 tmp = LOGICOP_OR_INV;
764 break;
765 case GL_NOR:
766 tmp = LOGICOP_NOR;
767 break;
768 case GL_EQUIV:
769 tmp = LOGICOP_EQUIV;
770 break;
771 case GL_INVERT:
772 tmp = LOGICOP_INV;
773 break;
774 case GL_OR_REVERSE:
775 tmp = LOGICOP_OR_RVRSE;
776 break;
777 case GL_NAND:
778 tmp = LOGICOP_NAND;
779 break;
780 case GL_SET:
781 tmp = LOGICOP_SET;
782 break;
783 default:
784 return;
785 }
786
787 I830_STATECHANGE(imesa, I830_UPLOAD_CTX);
788 imesa->Setup[I830_CTXREG_STATE4] &= ~LOGICOP_MASK;
789 imesa->Setup[I830_CTXREG_STATE4] |= LOGIC_OP_FUNC(tmp);
790
791 /* Make sure all the enables are correct */
792 i830EvalLogicOpBlendState(ctx);
793 }
794
795 /* Fallback to swrast for select and feedback.
796 */
797 static void i830RenderMode( GLcontext *ctx, GLenum mode )
798 {
799 i830ContextPtr imesa = I830_CONTEXT(ctx);
800 FALLBACK( imesa, I830_FALLBACK_RENDERMODE, (mode != GL_RENDER) );
801 }
802
803 static void i830DrawBuffer(GLcontext *ctx, GLenum mode )
804 {
805 i830ContextPtr imesa = I830_CONTEXT(ctx);
806
807 /*
808 * _ColorDrawBufferMask is easier to cope with than <mode>.
809 */
810 switch ( ctx->DrawBuffer->_ColorDrawBufferMask[0] ) {
811 case BUFFER_BIT_FRONT_LEFT:
812 I830_FIREVERTICES(imesa);
813 I830_STATECHANGE(imesa, I830_UPLOAD_BUFFERS);
814 imesa->BufferSetup[I830_DESTREG_CBUFADDR] = imesa->i830Screen->fbOffset;
815 i830XMesaSetFrontClipRects( imesa );
816 FALLBACK( imesa, I830_FALLBACK_DRAW_BUFFER, GL_FALSE );
817 break;
818 case BUFFER_BIT_BACK_LEFT:
819 I830_FIREVERTICES(imesa);
820 I830_STATECHANGE(imesa, I830_UPLOAD_BUFFERS);
821 imesa->BufferSetup[I830_DESTREG_CBUFADDR] =
822 imesa->i830Screen->backOffset;
823 i830XMesaSetBackClipRects( imesa );
824 FALLBACK( imesa, I830_FALLBACK_DRAW_BUFFER, GL_FALSE );
825 break;
826 default:
827 /* GL_NONE or GL_FRONT_AND_BACK or stereo left&right, etc */
828 FALLBACK( imesa, I830_FALLBACK_DRAW_BUFFER, GL_TRUE );
829 return;
830 }
831 }
832
833 static void i830ReadBuffer(GLcontext *ctx, GLenum mode )
834 {
835 /* nothing, until we implement h/w glRead/CopyPixels or CopyTexImage */
836 }
837
838 static void i830ClearColor(GLcontext *ctx, const GLfloat color[4])
839 {
840 i830ContextPtr imesa = I830_CONTEXT(ctx);
841
842 CLAMPED_FLOAT_TO_UBYTE(imesa->clear_red, color[0]);
843 CLAMPED_FLOAT_TO_UBYTE(imesa->clear_green, color[1]);
844 CLAMPED_FLOAT_TO_UBYTE(imesa->clear_blue, color[2]);
845 CLAMPED_FLOAT_TO_UBYTE(imesa->clear_alpha, color[3]);
846
847 imesa->ClearColor = i830PackColor(imesa->i830Screen->fbFormat,
848 imesa->clear_red,
849 imesa->clear_green,
850 imesa->clear_blue,
851 imesa->clear_alpha);
852 }
853
854 static void i830CullFaceFrontFace(GLcontext *ctx, GLenum unused)
855 {
856 i830ContextPtr imesa = I830_CONTEXT(ctx);
857 GLuint mode = CULLMODE_BOTH;
858
859 if (I830_DEBUG&DEBUG_DRI)
860 fprintf(stderr, "%s\n", __FUNCTION__);
861
862 if (ctx->Polygon.CullFaceMode != GL_FRONT_AND_BACK) {
863 mode = CULLMODE_CW;
864
865 if (ctx->Polygon.CullFaceMode == GL_FRONT)
866 mode ^= (CULLMODE_CW ^ CULLMODE_CCW);
867 if (ctx->Polygon.FrontFace != GL_CCW)
868 mode ^= (CULLMODE_CW ^ CULLMODE_CCW);
869 }
870
871 imesa->LcsCullMode = mode;
872
873 if (ctx->Polygon.CullFlag) {
874 I830_STATECHANGE(imesa, I830_UPLOAD_CTX);
875 imesa->Setup[I830_CTXREG_STATE3] &= ~CULLMODE_MASK;
876 imesa->Setup[I830_CTXREG_STATE3] |= ENABLE_CULL_MODE | mode;
877 }
878 }
879
880 static void i830LineWidth( GLcontext *ctx, GLfloat widthf )
881 {
882 i830ContextPtr imesa = I830_CONTEXT( ctx );
883 int width;
884
885 if (I830_DEBUG&DEBUG_DRI)
886 fprintf(stderr, "%s\n", __FUNCTION__);
887
888 width = FloatToInt(widthf * 2);
889 CLAMP_SELF(width, 1, 15);
890
891 I830_STATECHANGE(imesa, I830_UPLOAD_CTX);
892 imesa->Setup[I830_CTXREG_STATE5] &= ~FIXED_LINE_WIDTH_MASK;
893 imesa->Setup[I830_CTXREG_STATE5] |= (ENABLE_FIXED_LINE_WIDTH |
894 FIXED_LINE_WIDTH(width));
895 }
896
897 static void i830PointSize(GLcontext *ctx, GLfloat size)
898 {
899 i830ContextPtr imesa = I830_CONTEXT(ctx);
900 GLint point_size = FloatToInt(size);
901
902 if (I830_DEBUG&DEBUG_DRI)
903 fprintf(stderr, "%s\n", __FUNCTION__);
904
905 CLAMP_SELF(point_size, 1, 256);
906 I830_STATECHANGE(imesa, I830_UPLOAD_CTX);
907 imesa->Setup[I830_CTXREG_STATE5] &= ~FIXED_POINT_WIDTH_MASK;
908 imesa->Setup[I830_CTXREG_STATE5] |= (ENABLE_FIXED_POINT_WIDTH |
909 FIXED_POINT_WIDTH(point_size));
910 }
911
912
913 /* =============================================================
914 * Color masks
915 */
916
917 static void i830ColorMask(GLcontext *ctx,
918 GLboolean r, GLboolean g,
919 GLboolean b, GLboolean a)
920 {
921 i830ContextPtr imesa = I830_CONTEXT( ctx );
922 GLuint tmp = 0;
923
924 if (I830_DEBUG&DEBUG_DRI)
925 fprintf(stderr, "%s r(%d) g(%d) b(%d) a(%d)\n", __FUNCTION__, r, g, b, a);
926
927 imesa->mask_red = !r;
928 imesa->mask_green = !g;
929 imesa->mask_blue = !b;
930 imesa->mask_alpha = !a;
931
932 tmp = (imesa->Setup[I830_CTXREG_ENABLES_2] & ~WRITEMASK_MASK) |
933 ENABLE_COLOR_MASK |
934 ENABLE_COLOR_WRITE |
935 ((!r) << WRITEMASK_RED_SHIFT) |
936 ((!g) << WRITEMASK_GREEN_SHIFT) |
937 ((!b) << WRITEMASK_BLUE_SHIFT) |
938 ((!a) << WRITEMASK_ALPHA_SHIFT);
939
940 if (tmp != imesa->Setup[I830_CTXREG_ENABLES_2]) {
941 I830_FIREVERTICES(imesa);
942 imesa->dirty |= I830_UPLOAD_CTX;
943 imesa->Setup[I830_CTXREG_ENABLES_2] = tmp;
944 }
945 }
946
947 static void update_specular( GLcontext *ctx )
948 {
949 i830ContextPtr imesa = I830_CONTEXT( ctx );
950
951 I830_STATECHANGE(imesa, I830_UPLOAD_CTX);
952 imesa->Setup[I830_CTXREG_ENABLES_1] &= ~ENABLE_SPEC_ADD_MASK;
953
954 if (NEED_SECONDARY_COLOR(ctx))
955 imesa->Setup[I830_CTXREG_ENABLES_1] |= ENABLE_SPEC_ADD;
956 else
957 imesa->Setup[I830_CTXREG_ENABLES_1] |= DISABLE_SPEC_ADD;
958 }
959
960 static void i830LightModelfv(GLcontext *ctx, GLenum pname,
961 const GLfloat *param)
962 {
963 if (I830_DEBUG&DEBUG_DRI)
964 fprintf(stderr, "%s\n", __FUNCTION__);
965
966 if (pname == GL_LIGHT_MODEL_COLOR_CONTROL) {
967 update_specular( ctx );
968 }
969 }
970
971 /* In Mesa 3.5 we can reliably do native flatshading.
972 */
973 static void i830ShadeModel(GLcontext *ctx, GLenum mode)
974 {
975 i830ContextPtr imesa = I830_CONTEXT(ctx);
976 I830_STATECHANGE(imesa, I830_UPLOAD_CTX);
977
978
979 #define SHADE_MODE_MASK ((1<<10)|(1<<8)|(1<<6)|(1<<4))
980
981 imesa->Setup[I830_CTXREG_STATE3] &= ~SHADE_MODE_MASK;
982
983 if (mode == GL_FLAT) {
984 imesa->Setup[I830_CTXREG_STATE3] |= (ALPHA_SHADE_MODE(SHADE_MODE_FLAT) |
985 FOG_SHADE_MODE(SHADE_MODE_FLAT) |
986 SPEC_SHADE_MODE(SHADE_MODE_FLAT) |
987 COLOR_SHADE_MODE(SHADE_MODE_FLAT));
988 } else {
989 imesa->Setup[I830_CTXREG_STATE3] |= (ALPHA_SHADE_MODE(SHADE_MODE_LINEAR) |
990 FOG_SHADE_MODE(SHADE_MODE_LINEAR) |
991 SPEC_SHADE_MODE(SHADE_MODE_LINEAR) |
992 COLOR_SHADE_MODE(SHADE_MODE_LINEAR));
993 }
994 }
995
996 /* =============================================================
997 * Fog
998 */
999 static void i830Fogfv(GLcontext *ctx, GLenum pname, const GLfloat *param)
1000 {
1001 i830ContextPtr imesa = I830_CONTEXT(ctx);
1002
1003 if (I830_DEBUG&DEBUG_DRI)
1004 fprintf(stderr, "%s\n", __FUNCTION__);
1005
1006 if (pname == GL_FOG_COLOR) {
1007 GLuint color = (((GLubyte)(ctx->Fog.Color[0]*255.0F) << 16) |
1008 ((GLubyte)(ctx->Fog.Color[1]*255.0F) << 8) |
1009 ((GLubyte)(ctx->Fog.Color[2]*255.0F) << 0));
1010
1011 I830_STATECHANGE(imesa, I830_UPLOAD_CTX);
1012 imesa->Setup[I830_CTXREG_FOGCOLOR] = (STATE3D_FOG_COLOR_CMD | color);
1013 }
1014 }
1015
1016 /* =============================================================
1017 */
1018
1019 static void i830Enable(GLcontext *ctx, GLenum cap, GLboolean state)
1020 {
1021 i830ContextPtr imesa = I830_CONTEXT(ctx);
1022
1023 switch(cap) {
1024 case GL_LIGHTING:
1025 case GL_COLOR_SUM_EXT:
1026 update_specular( ctx );
1027 break;
1028
1029 case GL_ALPHA_TEST:
1030 I830_STATECHANGE(imesa, I830_UPLOAD_CTX);
1031 imesa->Setup[I830_CTXREG_ENABLES_1] &= ~ENABLE_DIS_ALPHA_TEST_MASK;
1032 if (state)
1033 imesa->Setup[I830_CTXREG_ENABLES_1] |= ENABLE_ALPHA_TEST;
1034 else
1035 imesa->Setup[I830_CTXREG_ENABLES_1] |= DISABLE_ALPHA_TEST;
1036
1037 break;
1038
1039 case GL_BLEND:
1040 case GL_COLOR_LOGIC_OP:
1041 case GL_INDEX_LOGIC_OP:
1042 i830EvalLogicOpBlendState(ctx);
1043 break;
1044
1045 case GL_DITHER:
1046 I830_STATECHANGE(imesa, I830_UPLOAD_CTX);
1047 imesa->Setup[I830_CTXREG_ENABLES_2] &= ~ENABLE_DITHER;
1048
1049 if (state)
1050 imesa->Setup[I830_CTXREG_ENABLES_2] |= ENABLE_DITHER;
1051 else
1052 imesa->Setup[I830_CTXREG_ENABLES_2] |= DISABLE_DITHER;
1053 break;
1054
1055 case GL_DEPTH_TEST:
1056 I830_STATECHANGE(imesa, I830_UPLOAD_CTX);
1057 imesa->Setup[I830_CTXREG_ENABLES_1] &= ~ENABLE_DIS_DEPTH_TEST_MASK;
1058
1059 if (state)
1060 imesa->Setup[I830_CTXREG_ENABLES_1] |= ENABLE_DEPTH_TEST;
1061 else
1062 imesa->Setup[I830_CTXREG_ENABLES_1] |= DISABLE_DEPTH_TEST;
1063
1064 /* Also turn off depth writes when GL_DEPTH_TEST is disabled:
1065 */
1066 i830DepthMask( ctx, state );
1067 break;
1068
1069 case GL_SCISSOR_TEST:
1070 I830_STATECHANGE(imesa, I830_UPLOAD_BUFFERS);
1071
1072 if (state)
1073 imesa->BufferSetup[I830_DESTREG_SENABLE] =
1074 (STATE3D_SCISSOR_ENABLE_CMD |
1075 ENABLE_SCISSOR_RECT);
1076 else
1077 imesa->BufferSetup[I830_DESTREG_SENABLE] =
1078 (STATE3D_SCISSOR_ENABLE_CMD |
1079 DISABLE_SCISSOR_RECT);
1080
1081 imesa->upload_cliprects = GL_TRUE;
1082 break;
1083
1084 case GL_LINE_SMOOTH:
1085 if (imesa->reduced_primitive == GL_LINES) {
1086 I830_STATECHANGE(imesa, I830_UPLOAD_CTX);
1087
1088 imesa->Setup[I830_CTXREG_AA] &= ~AA_LINE_ENABLE;
1089 if (state)
1090 imesa->Setup[I830_CTXREG_AA] |= AA_LINE_ENABLE;
1091 else
1092 imesa->Setup[I830_CTXREG_AA] |= AA_LINE_DISABLE;
1093 }
1094 break;
1095
1096 case GL_FOG:
1097 I830_STATECHANGE(imesa, I830_UPLOAD_CTX);
1098 imesa->Setup[I830_CTXREG_ENABLES_1] &= ~ENABLE_DIS_FOG_MASK;
1099 if (state)
1100 imesa->Setup[I830_CTXREG_ENABLES_1] |= I830_ENABLE_FOG;
1101 else
1102 imesa->Setup[I830_CTXREG_ENABLES_1] |= I830_DISABLE_FOG;
1103 break;
1104
1105 case GL_CULL_FACE:
1106 I830_STATECHANGE(imesa, I830_UPLOAD_CTX);
1107 imesa->Setup[I830_CTXREG_STATE3] &= ~CULLMODE_MASK;
1108 if (state)
1109 imesa->Setup[I830_CTXREG_STATE3] |= (ENABLE_CULL_MODE |
1110 imesa->LcsCullMode);
1111 else
1112 imesa->Setup[I830_CTXREG_STATE3] |= (ENABLE_CULL_MODE |
1113 CULLMODE_NONE);
1114 break;
1115
1116 case GL_TEXTURE_2D:
1117 /* I830_STATECHANGE(imesa, I830_UPLOAD_CTX); */
1118 /* imesa->Setup[I830_CTXREG_ENABLES_1] &= ~ENABLE_SPEC_ADD_MASK; */
1119 break;
1120
1121 case GL_STENCIL_TEST:
1122 if (imesa->hw_stencil) {
1123 I830_STATECHANGE(imesa, I830_UPLOAD_CTX);
1124 imesa->Setup[I830_CTXREG_ENABLES_1] &= ~ENABLE_STENCIL_TEST;
1125 imesa->Setup[I830_CTXREG_ENABLES_2] &= ~ENABLE_STENCIL_WRITE;
1126
1127 if (state) {
1128 imesa->Setup[I830_CTXREG_ENABLES_1] |= ENABLE_STENCIL_TEST;
1129 imesa->Setup[I830_CTXREG_ENABLES_2] |= ENABLE_STENCIL_WRITE;
1130 } else {
1131 imesa->Setup[I830_CTXREG_ENABLES_1] |= DISABLE_STENCIL_TEST;
1132 imesa->Setup[I830_CTXREG_ENABLES_2] |= DISABLE_STENCIL_WRITE;
1133 }
1134 } else {
1135 FALLBACK( imesa, I830_FALLBACK_STENCIL, state );
1136 }
1137 break;
1138
1139 case GL_POLYGON_STIPPLE:
1140 #if 0
1141 /* The stipple command worked on my 855GM box, but not my 845G.
1142 * I'll do more testing later to find out exactly which hardware
1143 * supports it. Disabled for now.
1144 */
1145 if (imesa->hw_stipple && imesa->reduced_primitive == GL_TRIANGLES)
1146 {
1147 I830_STATECHANGE(imesa, I830_UPLOAD_STIPPLE);
1148 imesa->StippleSetup[I830_STPREG_ST1] &= ~ST1_ENABLE;
1149 if (state)
1150 imesa->StippleSetup[I830_STPREG_ST1] |= ST1_ENABLE;
1151 }
1152 #endif
1153 break;
1154
1155 default:
1156 ;
1157 }
1158 }
1159
1160
1161 void i830EmitDrawingRectangle( i830ContextPtr imesa )
1162 {
1163 __DRIdrawablePrivate *dPriv = imesa->driDrawable;
1164 i830ScreenPrivate *i830Screen = imesa->i830Screen;
1165 int x0 = imesa->drawX;
1166 int y0 = imesa->drawY;
1167 int x1 = x0 + dPriv->w;
1168 int y1 = y0 + dPriv->h;
1169
1170 /* Don't set drawing rectangle */
1171 if (I830_DEBUG & DEBUG_IOCTL)
1172 fprintf(stderr, "%s x0(%d) x1(%d) y0(%d) y1(%d)\n", __FUNCTION__,
1173 x0, x1, y0, y1);
1174
1175 /* Coordinate origin of the window - may be offscreen.
1176 */
1177 imesa->BufferSetup[I830_DESTREG_DR4] = ((y0<<16) |
1178 (((unsigned)x0)&0xFFFF));
1179
1180 /* Clip to screen.
1181 */
1182 if (x0 < 0) x0 = 0;
1183 if (y0 < 0) y0 = 0;
1184 if (x1 > i830Screen->width-1) x1 = i830Screen->width-1;
1185 if (y1 > i830Screen->height-1) y1 = i830Screen->height-1;
1186
1187
1188 /* Onscreen drawing rectangle.
1189 */
1190 imesa->BufferSetup[I830_DESTREG_DR2] = ((y0<<16) | x0);
1191 imesa->BufferSetup[I830_DESTREG_DR3] = (((y1+1)<<16) | (x1+1));
1192
1193
1194 /* Just add in our dirty flag, since we might be called when locked */
1195 /* Might want to modify how this is done. */
1196 imesa->dirty |= I830_UPLOAD_BUFFERS;
1197
1198 if (0)
1199 fprintf(stderr, "[%s] DR2(0x%08x) DR3(0x%08x) DR4(0x%08x)\n",
1200 __FUNCTION__,
1201 imesa->BufferSetup[I830_DESTREG_DR2],
1202 imesa->BufferSetup[I830_DESTREG_DR3],
1203 imesa->BufferSetup[I830_DESTREG_DR4]);
1204 }
1205
1206 /* This could be done in hardware, will do once I have the driver
1207 * up and running.
1208 */
1209 static void i830CalcViewport( GLcontext *ctx )
1210 {
1211 i830ContextPtr imesa = I830_CONTEXT(ctx);
1212 const GLfloat *v = ctx->Viewport._WindowMap.m;
1213 GLfloat *m = imesa->ViewportMatrix.m;
1214
1215 /* See also i830_translate_vertex. SUBPIXEL adjustments can be done
1216 * via state vars, too.
1217 */
1218 m[MAT_SX] = v[MAT_SX];
1219 m[MAT_TX] = v[MAT_TX] + SUBPIXEL_X;
1220 m[MAT_SY] = - v[MAT_SY];
1221 m[MAT_TY] = - v[MAT_TY] + imesa->driDrawable->h + SUBPIXEL_Y;
1222 m[MAT_SZ] = v[MAT_SZ] * imesa->depth_scale;
1223 m[MAT_TZ] = v[MAT_TZ] * imesa->depth_scale;
1224 }
1225
1226 static void i830Viewport( GLcontext *ctx,
1227 GLint x, GLint y,
1228 GLsizei width, GLsizei height )
1229 {
1230 /* update size of Mesa/software ancillary buffers */
1231 _mesa_ResizeBuffersMESA();
1232 i830CalcViewport( ctx );
1233 }
1234
1235 static void i830DepthRange( GLcontext *ctx,
1236 GLclampd nearval, GLclampd farval )
1237 {
1238 i830CalcViewport( ctx );
1239 }
1240
1241 void i830PrintDirty( const char *msg, GLuint state )
1242 {
1243 fprintf(stderr, "%s (0x%x): %s%s%s%s%s%s%s%s%s%s%s\n",
1244 msg,
1245 (unsigned int) state,
1246 (state & I830_UPLOAD_TEX0) ? "upload-tex0, " : "",
1247 (state & I830_UPLOAD_TEX1) ? "upload-tex1, " : "",
1248 (state & I830_UPLOAD_TEX2) ? "upload-tex2, " : "",
1249 (state & I830_UPLOAD_TEX3) ? "upload-tex3, " : "",
1250 (state & I830_UPLOAD_CTX) ? "upload-ctx, " : "",
1251 (state & I830_UPLOAD_BUFFERS) ? "upload-bufs, " : "",
1252 (state & I830_UPLOAD_TEXBLEND0) ? "upload-blend0, " : "",
1253 (state & I830_UPLOAD_TEXBLEND1) ? "upload-blend1, " : "",
1254 (state & I830_UPLOAD_TEXBLEND2) ? "upload-blend2, " : "",
1255 (state & I830_UPLOAD_TEXBLEND3) ? "upload-blend3, " : "",
1256 (state & I830_UPLOAD_STIPPLE) ? "stipple, " : ""
1257 );
1258 }
1259
1260 /* Push the state into the sarea and/or texture memory.
1261 */
1262 void i830EmitHwStateLocked( i830ContextPtr imesa )
1263 {
1264 int i;
1265
1266 if (I830_DEBUG & DEBUG_STATE)
1267 i830PrintDirty( __FUNCTION__, imesa->dirty );
1268
1269 for ( i = 0 ; i < imesa->glCtx->Const.MaxTextureUnits ; i++ ) {
1270 if ( ((imesa->dirty & I830_UPLOAD_TEX_N_IMAGE( i )) != 0)
1271 && (imesa->CurrentTexObj[i] != NULL) ) {
1272 i830UploadTexImagesLocked(imesa, imesa->CurrentTexObj[i]);
1273 }
1274 }
1275
1276 if (imesa->dirty & I830_UPLOAD_CTX) {
1277 memcpy( imesa->sarea->ContextState,
1278 imesa->Setup, sizeof(imesa->Setup) );
1279 }
1280
1281 for ( i = 0 ; i < imesa->glCtx->Const.MaxTextureUnits ; i++ ) {
1282 if ((imesa->dirty & I830_UPLOAD_TEX_N(i)) && imesa->CurrentTexObj[i]) {
1283 unsigned * TexState;
1284
1285 imesa->sarea->dirty |= I830_UPLOAD_TEX_N(i);
1286
1287 switch( i ) {
1288 case 0:
1289 case 1:
1290 TexState = imesa->sarea->TexState[i];
1291 break;
1292
1293 case 2:
1294 TexState = imesa->sarea->TexState2;
1295 break;
1296
1297 case 3:
1298 TexState = imesa->sarea->TexState3;
1299 break;
1300 }
1301
1302 memcpy(TexState, imesa->CurrentTexObj[i]->Setup,
1303 sizeof(imesa->sarea->TexState[i]));
1304
1305 TexState[I830_TEXREG_TM0S3] &= ~TM0S3_LOD_BIAS_MASK;
1306 TexState[I830_TEXREG_TM0S3] |= imesa->LodBias[i];
1307
1308 /* Update the LRU usage */
1309 if (imesa->CurrentTexObj[i]->base.memBlock)
1310 driUpdateTextureLRU( (driTextureObject *)
1311 imesa->CurrentTexObj[i] );
1312 }
1313 }
1314 /* Need to figure out if texturing state, or enable changed. */
1315
1316 for ( i = 0 ; i < imesa->glCtx->Const.MaxTextureUnits ; i++ ) {
1317 if (imesa->dirty & I830_UPLOAD_TEXBLEND_N(i)) {
1318 unsigned * TexBlendState;
1319 unsigned * words_used;
1320
1321 imesa->sarea->dirty |= I830_UPLOAD_TEXBLEND_N(i);
1322
1323 switch( i ) {
1324 case 0:
1325 case 1:
1326 TexBlendState = imesa->sarea->TexBlendState[i];
1327 words_used = & imesa->sarea->TexBlendStateWordsUsed[i];
1328 break;
1329
1330 case 2:
1331 TexBlendState = imesa->sarea->TexBlendState2;
1332 words_used = & imesa->sarea->TexBlendStateWordsUsed2;
1333 break;
1334
1335 case 3:
1336 TexBlendState = imesa->sarea->TexBlendState3;
1337 words_used = & imesa->sarea->TexBlendStateWordsUsed3;
1338 break;
1339 }
1340
1341 memcpy(TexBlendState, imesa->TexBlend[i],
1342 imesa->TexBlendWordsUsed[i] * 4);
1343 *words_used = imesa->TexBlendWordsUsed[i];
1344 }
1345 }
1346
1347 if (imesa->dirty & I830_UPLOAD_BUFFERS) {
1348 memcpy( imesa->sarea->BufferState,imesa->BufferSetup,
1349 sizeof(imesa->BufferSetup) );
1350 }
1351
1352 if (imesa->dirty & I830_UPLOAD_STIPPLE) {
1353 memcpy( imesa->sarea->StippleState,imesa->StippleSetup,
1354 sizeof(imesa->StippleSetup) );
1355 }
1356
1357 if (imesa->dirty & I830_UPLOAD_TEX_PALETTE_SHARED) {
1358 memcpy( imesa->sarea->Palette[0],imesa->palette,
1359 sizeof(imesa->sarea->Palette[0]));
1360 } else {
1361 i830TextureObjectPtr p;
1362 if (imesa->dirty & I830_UPLOAD_TEX_PALETTE_N(0)) {
1363 p = imesa->CurrentTexObj[0];
1364 memcpy( imesa->sarea->Palette[0],p->palette,
1365 sizeof(imesa->sarea->Palette[0]));
1366 }
1367 if (imesa->dirty & I830_UPLOAD_TEX_PALETTE_N(1)) {
1368 p = imesa->CurrentTexObj[1];
1369 memcpy( imesa->sarea->Palette[1],
1370 p->palette,
1371 sizeof(imesa->sarea->Palette[1]));
1372 }
1373 }
1374
1375 imesa->sarea->dirty |= (imesa->dirty & ~(I830_UPLOAD_TEX_MASK |
1376 I830_UPLOAD_TEXBLEND_MASK));
1377
1378 imesa->upload_cliprects = GL_TRUE;
1379 imesa->dirty = 0;
1380 }
1381
1382
1383 void i830DDInitState( GLcontext *ctx )
1384 {
1385 i830ContextPtr imesa = I830_CONTEXT(ctx);
1386 i830ScreenPrivate *i830Screen = imesa->i830Screen;
1387 int i;
1388
1389 imesa->clear_red = 0;
1390 imesa->clear_green = 0;
1391 imesa->clear_blue = 0;
1392 imesa->clear_alpha = 0;
1393
1394 imesa->mask_red = GL_FALSE;
1395 imesa->mask_green = GL_FALSE;
1396 imesa->mask_blue = GL_FALSE;
1397 imesa->mask_alpha = GL_FALSE;
1398
1399 /* Zero all texture state */
1400 for (i = 0; i < I830_MAX_TEXTURE_UNITS; i++) {
1401 (void) memset( imesa->TexBlend[i], 0, sizeof( imesa->TexBlend[i] ) );
1402 (void) memset( imesa->Init_TexBlend[i], 0, sizeof( imesa->Init_TexBlend[i] ) );
1403
1404 imesa->TexBlendWordsUsed[i] = 0;
1405 imesa->Init_TexBlendWordsUsed[i] = 0;
1406 }
1407
1408 /* Set default blend state */
1409 imesa->TexBlend[0][0] = (STATE3D_MAP_BLEND_OP_CMD(0) |
1410 TEXPIPE_COLOR |
1411 ENABLE_TEXOUTPUT_WRT_SEL |
1412 TEXOP_OUTPUT_CURRENT |
1413 DISABLE_TEX_CNTRL_STAGE |
1414 TEXOP_SCALE_1X |
1415 TEXOP_MODIFY_PARMS |
1416 TEXOP_LAST_STAGE |
1417 TEXBLENDOP_ARG1);
1418 imesa->TexBlend[0][1] = (STATE3D_MAP_BLEND_OP_CMD(0) |
1419 TEXPIPE_ALPHA |
1420 ENABLE_TEXOUTPUT_WRT_SEL |
1421 TEXOP_OUTPUT_CURRENT |
1422 TEXOP_SCALE_1X |
1423 TEXOP_MODIFY_PARMS |
1424 TEXBLENDOP_ARG1);
1425 imesa->TexBlend[0][2] = (STATE3D_MAP_BLEND_ARG_CMD(0) |
1426 TEXPIPE_COLOR |
1427 TEXBLEND_ARG1 |
1428 TEXBLENDARG_MODIFY_PARMS |
1429 TEXBLENDARG_DIFFUSE);
1430 imesa->TexBlend[0][3] = (STATE3D_MAP_BLEND_ARG_CMD(0) |
1431 TEXPIPE_ALPHA |
1432 TEXBLEND_ARG1 |
1433 TEXBLENDARG_MODIFY_PARMS |
1434 TEXBLENDARG_DIFFUSE);
1435
1436 imesa->TexBlendWordsUsed[0] = 4;
1437
1438 imesa->Init_TexBlend[0][0] = (STATE3D_MAP_BLEND_OP_CMD(0) |
1439 TEXPIPE_COLOR |
1440 ENABLE_TEXOUTPUT_WRT_SEL |
1441 TEXOP_OUTPUT_CURRENT |
1442 DISABLE_TEX_CNTRL_STAGE |
1443 TEXOP_SCALE_1X |
1444 TEXOP_MODIFY_PARMS |
1445 TEXOP_LAST_STAGE |
1446 TEXBLENDOP_ARG1);
1447 imesa->Init_TexBlend[0][1] = (STATE3D_MAP_BLEND_OP_CMD(0) |
1448 TEXPIPE_ALPHA |
1449 ENABLE_TEXOUTPUT_WRT_SEL |
1450 TEXOP_OUTPUT_CURRENT |
1451 TEXOP_SCALE_1X |
1452 TEXOP_MODIFY_PARMS |
1453 TEXBLENDOP_ARG1);
1454 imesa->Init_TexBlend[0][2] = (STATE3D_MAP_BLEND_ARG_CMD(0) |
1455 TEXPIPE_COLOR |
1456 TEXBLEND_ARG1 |
1457 TEXBLENDARG_MODIFY_PARMS |
1458 TEXBLENDARG_CURRENT);
1459 imesa->Init_TexBlend[0][3] = (STATE3D_MAP_BLEND_ARG_CMD(0) |
1460 TEXPIPE_ALPHA |
1461 TEXBLEND_ARG1 |
1462 TEXBLENDARG_MODIFY_PARMS |
1463 TEXBLENDARG_CURRENT);
1464 imesa->Init_TexBlendWordsUsed[0] = 4;
1465
1466 memset(imesa->Setup, 0, sizeof(imesa->Setup));
1467
1468 imesa->Setup[I830_CTXREG_VF] = 0;
1469 imesa->Setup[I830_CTXREG_VF2] = 0;
1470
1471 imesa->Setup[I830_CTXREG_AA] = (STATE3D_AA_CMD |
1472 AA_LINE_ECAAR_WIDTH_ENABLE |
1473 AA_LINE_ECAAR_WIDTH_1_0 |
1474 AA_LINE_REGION_WIDTH_ENABLE |
1475 AA_LINE_REGION_WIDTH_1_0 |
1476 AA_LINE_DISABLE);
1477
1478 imesa->Setup[I830_CTXREG_ENABLES_1] = (STATE3D_ENABLES_1_CMD |
1479 DISABLE_LOGIC_OP |
1480 DISABLE_STENCIL_TEST |
1481 DISABLE_DEPTH_BIAS |
1482 DISABLE_SPEC_ADD |
1483 I830_DISABLE_FOG |
1484 DISABLE_ALPHA_TEST |
1485 DISABLE_COLOR_BLEND |
1486 DISABLE_DEPTH_TEST);
1487
1488 if (imesa->hw_stencil) {
1489 imesa->Setup[I830_CTXREG_ENABLES_2] = (STATE3D_ENABLES_2_CMD |
1490 ENABLE_STENCIL_WRITE |
1491 ENABLE_TEX_CACHE |
1492 ENABLE_DITHER |
1493 ENABLE_COLOR_MASK |
1494 /* set no color comps disabled */
1495 ENABLE_COLOR_WRITE |
1496 ENABLE_DEPTH_WRITE);
1497 } else {
1498 imesa->Setup[I830_CTXREG_ENABLES_2] = (STATE3D_ENABLES_2_CMD |
1499 DISABLE_STENCIL_WRITE |
1500 ENABLE_TEX_CACHE |
1501 ENABLE_DITHER |
1502 ENABLE_COLOR_MASK |
1503 /* set no color comps disabled */
1504 ENABLE_COLOR_WRITE |
1505 ENABLE_DEPTH_WRITE);
1506 }
1507
1508 imesa->Setup[I830_CTXREG_STATE1] = (STATE3D_MODES_1_CMD |
1509 ENABLE_COLR_BLND_FUNC |
1510 BLENDFUNC_ADD |
1511 ENABLE_SRC_BLND_FACTOR |
1512 SRC_BLND_FACT(BLENDFACT_ONE) |
1513 ENABLE_DST_BLND_FACTOR |
1514 DST_BLND_FACT(BLENDFACT_ZERO) );
1515
1516 imesa->Setup[I830_CTXREG_STATE2] = (STATE3D_MODES_2_CMD |
1517 ENABLE_GLOBAL_DEPTH_BIAS |
1518 GLOBAL_DEPTH_BIAS(0) |
1519 ENABLE_ALPHA_TEST_FUNC |
1520 ALPHA_TEST_FUNC(COMPAREFUNC_ALWAYS) |
1521 ALPHA_REF_VALUE(0) );
1522
1523 imesa->Setup[I830_CTXREG_STATE3] = (STATE3D_MODES_3_CMD |
1524 ENABLE_DEPTH_TEST_FUNC |
1525 DEPTH_TEST_FUNC(COMPAREFUNC_LESS) |
1526 ENABLE_ALPHA_SHADE_MODE |
1527 ALPHA_SHADE_MODE(SHADE_MODE_LINEAR) |
1528 ENABLE_FOG_SHADE_MODE |
1529 FOG_SHADE_MODE(SHADE_MODE_LINEAR) |
1530 ENABLE_SPEC_SHADE_MODE |
1531 SPEC_SHADE_MODE(SHADE_MODE_LINEAR) |
1532 ENABLE_COLOR_SHADE_MODE |
1533 COLOR_SHADE_MODE(SHADE_MODE_LINEAR) |
1534 ENABLE_CULL_MODE |
1535 CULLMODE_NONE);
1536
1537 imesa->Setup[I830_CTXREG_STATE4] = (STATE3D_MODES_4_CMD |
1538 ENABLE_LOGIC_OP_FUNC |
1539 LOGIC_OP_FUNC(LOGICOP_COPY) |
1540 ENABLE_STENCIL_TEST_MASK |
1541 STENCIL_TEST_MASK(0xff) |
1542 ENABLE_STENCIL_WRITE_MASK |
1543 STENCIL_WRITE_MASK(0xff));
1544
1545 imesa->Setup[I830_CTXREG_STENCILTST] = (STATE3D_STENCIL_TEST_CMD |
1546 ENABLE_STENCIL_PARMS |
1547 STENCIL_FAIL_OP(STENCILOP_KEEP) |
1548 STENCIL_PASS_DEPTH_FAIL_OP(STENCILOP_KEEP) |
1549 STENCIL_PASS_DEPTH_PASS_OP(STENCILOP_KEEP) |
1550 ENABLE_STENCIL_TEST_FUNC |
1551 STENCIL_TEST_FUNC(COMPAREFUNC_ALWAYS) |
1552 ENABLE_STENCIL_REF_VALUE |
1553 STENCIL_REF_VALUE(0) );
1554
1555 imesa->Setup[I830_CTXREG_STATE5] = (STATE3D_MODES_5_CMD |
1556 FLUSH_TEXTURE_CACHE |
1557 ENABLE_SPRITE_POINT_TEX |
1558 SPRITE_POINT_TEX_OFF |
1559 ENABLE_FIXED_LINE_WIDTH |
1560 FIXED_LINE_WIDTH(0x2) | /* 1.0 */
1561 ENABLE_FIXED_POINT_WIDTH |
1562 FIXED_POINT_WIDTH(1) );
1563
1564 imesa->Setup[I830_CTXREG_IALPHAB] = (STATE3D_INDPT_ALPHA_BLEND_CMD |
1565 DISABLE_INDPT_ALPHA_BLEND |
1566 ENABLE_ALPHA_BLENDFUNC |
1567 ABLENDFUNC_ADD);
1568
1569 imesa->Setup[I830_CTXREG_FOGCOLOR] = (STATE3D_FOG_COLOR_CMD |
1570 FOG_COLOR_RED(0) |
1571 FOG_COLOR_GREEN(0) |
1572 FOG_COLOR_BLUE(0));
1573
1574 imesa->Setup[I830_CTXREG_BLENDCOLR0] = (STATE3D_CONST_BLEND_COLOR_CMD);
1575
1576 imesa->Setup[I830_CTXREG_BLENDCOLR] = 0;
1577
1578 imesa->Setup[I830_CTXREG_MCSB0] = STATE3D_MAP_COORD_SETBIND_CMD;
1579 imesa->Setup[I830_CTXREG_MCSB1] = (TEXBIND_SET3(TEXCOORDSRC_VTXSET_3) |
1580 TEXBIND_SET2(TEXCOORDSRC_VTXSET_2) |
1581 TEXBIND_SET1(TEXCOORDSRC_VTXSET_1) |
1582 TEXBIND_SET0(TEXCOORDSRC_VTXSET_0));
1583
1584 imesa->LcsCullMode = CULLMODE_CW; /* GL default */
1585
1586 memset(imesa->BufferSetup, 0, sizeof(imesa->BufferSetup));
1587 memset(imesa->StippleSetup, 0, sizeof(imesa->StippleSetup));
1588
1589
1590 if (imesa->glCtx->Visual.doubleBufferMode &&
1591 imesa->sarea->pf_current_page == 0) {
1592 imesa->drawMap = i830Screen->back.map;
1593 imesa->readMap = i830Screen->back.map;
1594 imesa->BufferSetup[I830_DESTREG_CBUFADDR] = i830Screen->backOffset;
1595 imesa->BufferSetup[I830_DESTREG_DBUFADDR] = 0;
1596 } else {
1597 /* use front buffer by default */
1598 imesa->drawMap = (char *)imesa->driScreen->pFB;
1599 imesa->readMap = (char *)imesa->driScreen->pFB;
1600 imesa->BufferSetup[I830_DESTREG_CBUFADDR] = i830Screen->fbOffset;
1601 imesa->BufferSetup[I830_DESTREG_DBUFADDR] = 0;
1602 }
1603
1604 imesa->BufferSetup[I830_DESTREG_DV0] = STATE3D_DST_BUF_VARS_CMD;
1605
1606 switch (i830Screen->fbFormat) {
1607 case DV_PF_555:
1608 case DV_PF_565:
1609 imesa->BufferSetup[I830_DESTREG_DV1] = (DSTORG_HORT_BIAS(0x8) | /* .5 */
1610 DSTORG_VERT_BIAS(0x8) | /* .5 */
1611 i830Screen->fbFormat |
1612 DEPTH_IS_Z |
1613 DEPTH_FRMT_16_FIXED);
1614 break;
1615 case DV_PF_8888:
1616 imesa->BufferSetup[I830_DESTREG_DV1] = (DSTORG_HORT_BIAS(0x8) | /* .5 */
1617 DSTORG_VERT_BIAS(0x8) | /* .5 */
1618 i830Screen->fbFormat |
1619 DEPTH_IS_Z |
1620 DEPTH_FRMT_24_FIXED_8_OTHER);
1621 break;
1622 }
1623 imesa->BufferSetup[I830_DESTREG_SENABLE] = (STATE3D_SCISSOR_ENABLE_CMD |
1624 DISABLE_SCISSOR_RECT);
1625 imesa->BufferSetup[I830_DESTREG_SR0] = STATE3D_SCISSOR_RECT_0_CMD;
1626 imesa->BufferSetup[I830_DESTREG_SR1] = 0;
1627 imesa->BufferSetup[I830_DESTREG_SR2] = 0;
1628
1629 imesa->BufferSetup[I830_DESTREG_DR0] = STATE3D_DRAW_RECT_CMD;
1630 imesa->BufferSetup[I830_DESTREG_DR1] = 0;
1631 imesa->BufferSetup[I830_DESTREG_DR2] = 0;
1632 imesa->BufferSetup[I830_DESTREG_DR3] = (((i830Screen->height)<<16) |
1633 (i830Screen->width));
1634 imesa->BufferSetup[I830_DESTREG_DR4] = 0;
1635
1636 memcpy( imesa->Init_Setup,
1637 imesa->Setup,
1638 sizeof(imesa->Setup) );
1639 memcpy( imesa->Init_BufferSetup,
1640 imesa->BufferSetup,
1641 sizeof(imesa->BufferSetup) );
1642
1643 }
1644
1645 static void i830InvalidateState( GLcontext *ctx, GLuint new_state )
1646 {
1647 _swrast_InvalidateState( ctx, new_state );
1648 _swsetup_InvalidateState( ctx, new_state );
1649 _ac_InvalidateState( ctx, new_state );
1650 _tnl_InvalidateState( ctx, new_state );
1651 I830_CONTEXT(ctx)->NewGLState |= new_state;
1652 }
1653
1654 void i830DDInitStateFuncs(GLcontext *ctx)
1655 {
1656 /* Callbacks for internal Mesa events.
1657 */
1658 ctx->Driver.UpdateState = i830InvalidateState;
1659
1660 /* API callbacks
1661 */
1662 ctx->Driver.AlphaFunc = i830AlphaFunc;
1663 ctx->Driver.BlendEquationSeparate = i830BlendEquationSeparate;
1664 ctx->Driver.BlendFuncSeparate = i830BlendFuncSeparate;
1665 ctx->Driver.BlendColor = i830BlendColor;
1666 ctx->Driver.ClearColor = i830ClearColor;
1667 ctx->Driver.ColorMask = i830ColorMask;
1668 ctx->Driver.CullFace = i830CullFaceFrontFace;
1669 ctx->Driver.DepthFunc = i830DepthFunc;
1670 ctx->Driver.DepthMask = i830DepthMask;
1671 ctx->Driver.Enable = i830Enable;
1672 ctx->Driver.Fogfv = i830Fogfv;
1673 ctx->Driver.FrontFace = i830CullFaceFrontFace;
1674 ctx->Driver.LineWidth = i830LineWidth;
1675 ctx->Driver.PointSize = i830PointSize;
1676 ctx->Driver.LogicOpcode = i830LogicOp;
1677 ctx->Driver.PolygonStipple = i830PolygonStippleFallback;
1678 ctx->Driver.RenderMode = i830RenderMode;
1679 ctx->Driver.Scissor = i830Scissor;
1680 ctx->Driver.DrawBuffer = i830DrawBuffer;
1681 ctx->Driver.ReadBuffer = i830ReadBuffer;
1682 ctx->Driver.ShadeModel = i830ShadeModel;
1683 ctx->Driver.DepthRange = i830DepthRange;
1684 ctx->Driver.Viewport = i830Viewport;
1685 ctx->Driver.LightModelfv = i830LightModelfv;
1686
1687 ctx->Driver.StencilFuncSeparate = i830StencilFuncSeparate;
1688 ctx->Driver.StencilMaskSeparate = i830StencilMaskSeparate;
1689 ctx->Driver.StencilOpSeparate = i830StencilOpSeparate;
1690
1691 /* Pixel path fallbacks.
1692 */
1693 ctx->Driver.Accum = _swrast_Accum;
1694 ctx->Driver.Bitmap = _swrast_Bitmap;
1695 ctx->Driver.CopyPixels = _swrast_CopyPixels;
1696 ctx->Driver.DrawPixels = _swrast_DrawPixels;
1697 ctx->Driver.ReadPixels = _swrast_ReadPixels;
1698
1699 /* Swrast hooks for imaging extensions:
1700 */
1701 ctx->Driver.CopyColorTable = _swrast_CopyColorTable;
1702 ctx->Driver.CopyColorSubTable = _swrast_CopyColorSubTable;
1703 ctx->Driver.CopyConvolutionFilter1D = _swrast_CopyConvolutionFilter1D;
1704 ctx->Driver.CopyConvolutionFilter2D = _swrast_CopyConvolutionFilter2D;
1705 }