2 * Copyright 2000-2001 VA Linux Systems, Inc.
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * on the rights to use, copy, modify, merge, publish, distribute, sub
9 * license, and/or sell copies of the Software, and to permit persons to whom
10 * the Software is furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
19 * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 * OTHER DEALINGS IN THE SOFTWARE.
25 * Keith Whitwell <keith@tungstengraphics.com>
27 /* $XFree86: xc/lib/GL/mesa/src/drv/mga/mgastate.c,v 1.13 2002/10/30 12:51:36 alanh Exp $ */
35 #include "mgacontext.h"
44 #include "swrast/swrast.h"
45 #include "array_cache/acache.h"
47 #include "tnl/t_context.h"
48 #include "tnl/t_pipeline.h"
49 #include "swrast_setup/swrast_setup.h"
52 static void updateSpecularLighting( GLcontext
*ctx
);
55 /* Some outstanding problems with accelerating logic ops...
57 #if defined(ACCEL_ROP)
58 static const GLuint mgarop_NoBLK
[16] = {
59 DC_atype_rpl
| 0x00000000, DC_atype_rstr
| 0x00080000,
60 DC_atype_rstr
| 0x00040000, DC_atype_rpl
| 0x000c0000,
61 DC_atype_rstr
| 0x00020000, DC_atype_rstr
| 0x000a0000,
62 DC_atype_rstr
| 0x00060000, DC_atype_rstr
| 0x000e0000,
63 DC_atype_rstr
| 0x00010000, DC_atype_rstr
| 0x00090000,
64 DC_atype_rstr
| 0x00050000, DC_atype_rstr
| 0x000d0000,
65 DC_atype_rpl
| 0x00030000, DC_atype_rstr
| 0x000b0000,
66 DC_atype_rstr
| 0x00070000, DC_atype_rpl
| 0x000f0000
71 /* =============================================================
75 static void mgaDDAlphaFunc(GLcontext
*ctx
, GLenum func
, GLfloat ref
)
77 mgaContextPtr mmesa
= MGA_CONTEXT(ctx
);
81 CLAMPED_FLOAT_TO_UBYTE(refByte
, ref
);
107 a
= AC_atmode_noacmp
;
114 FLUSH_BATCH( mmesa
);
115 mmesa
->hw
.alpha_func
= a
| MGA_FIELD( AC_atref
, refByte
);
116 mmesa
->dirty
|= MGA_UPLOAD_CONTEXT
;
119 static void mgaDDBlendEquation(GLcontext
*ctx
, GLenum mode
)
121 FLUSH_BATCH( MGA_CONTEXT(ctx
) );
123 /* BlendEquation sets ColorLogicOpEnabled in an unexpected
126 FALLBACK( ctx
, MGA_FALLBACK_LOGICOP
,
127 (ctx
->Color
.ColorLogicOpEnabled
&&
128 ctx
->Color
.LogicOp
!= GL_COPY
));
131 static void mgaDDBlendFunc(GLcontext
*ctx
, GLenum sfactor
, GLenum dfactor
)
133 mgaContextPtr mmesa
= MGA_CONTEXT(ctx
);
134 mgaScreenPrivate
*mgaScreen
= mmesa
->mgaScreen
;
138 switch (ctx
->Color
.BlendSrcRGB
) {
140 src
= AC_src_zero
; break;
142 src
= AC_src_src_alpha
; break;
144 default: /* never happens */
145 src
= AC_src_one
; break;
147 src
= AC_src_dst_color
; break;
148 case GL_ONE_MINUS_DST_COLOR
:
149 src
= AC_src_om_dst_color
; break;
150 case GL_ONE_MINUS_SRC_ALPHA
:
151 src
= AC_src_om_src_alpha
; break;
153 src
= (mgaScreen
->cpp
== 4)
154 ? AC_src_dst_alpha
: AC_src_one
;
156 case GL_ONE_MINUS_DST_ALPHA
:
157 src
= (mgaScreen
->cpp
== 4)
158 ? AC_src_om_dst_alpha
: AC_src_zero
;
160 case GL_SRC_ALPHA_SATURATE
:
161 src
= (ctx
->Visual
.alphaBits
> 0)
162 ? AC_src_src_alpha_sat
: AC_src_zero
;
166 switch (ctx
->Color
.BlendDstRGB
) {
168 dst
= AC_dst_src_alpha
; break;
169 case GL_ONE_MINUS_SRC_ALPHA
:
170 dst
= AC_dst_om_src_alpha
; break;
171 default: /* never happens */
173 dst
= AC_dst_zero
; break;
175 dst
= AC_dst_one
; break;
177 dst
= AC_dst_src_color
; break;
178 case GL_ONE_MINUS_SRC_COLOR
:
179 dst
= AC_dst_om_src_color
; break;
181 dst
= (mgaScreen
->cpp
== 4)
182 ? AC_dst_dst_alpha
: AC_dst_one
;
184 case GL_ONE_MINUS_DST_ALPHA
:
185 dst
= (mgaScreen
->cpp
== 4)
186 ? AC_dst_om_dst_alpha
: AC_dst_zero
;
190 FLUSH_BATCH( mmesa
);
191 mmesa
->hw
.blend_func
= (src
| dst
);
192 mmesa
->dirty
|= MGA_UPLOAD_CONTEXT
;
195 static void mgaDDBlendFuncSeparate( GLcontext
*ctx
, GLenum sfactorRGB
,
196 GLenum dfactorRGB
, GLenum sfactorA
,
199 mgaDDBlendFunc( ctx
, sfactorRGB
, dfactorRGB
);
203 /* =============================================================
207 static void mgaDDDepthFunc(GLcontext
*ctx
, GLenum func
)
209 mgaContextPtr mmesa
= MGA_CONTEXT( ctx
);
214 /* can't do this in h/w, we'll use a s/w fallback */
215 FALLBACK (ctx
, MGA_FALLBACK_DEPTH
, ctx
->Depth
.Test
);
219 zmode
= DC_zmode_nozcmp
; break;
221 zmode
= DC_zmode_zlt
; break;
223 zmode
= DC_zmode_zlte
; break;
225 zmode
= DC_zmode_ze
; break;
227 zmode
= DC_zmode_zgt
; break;
229 zmode
= DC_zmode_zgte
; break;
231 zmode
= DC_zmode_zne
; break;
236 FLUSH_BATCH( mmesa
);
237 mmesa
->hw
.zmode
&= DC_zmode_MASK
;
238 mmesa
->hw
.zmode
|= zmode
;
239 mmesa
->dirty
|= MGA_UPLOAD_CONTEXT
;
242 static void mgaDDDepthMask(GLcontext
*ctx
, GLboolean flag
)
244 mgaContextPtr mmesa
= MGA_CONTEXT( ctx
);
247 FLUSH_BATCH( mmesa
);
248 mmesa
->hw
.zmode
&= DC_atype_MASK
;
249 mmesa
->hw
.zmode
|= (flag
) ? DC_atype_zi
: DC_atype_i
;
250 mmesa
->dirty
|= MGA_UPLOAD_CONTEXT
;
254 static void mgaDDClearDepth(GLcontext
*ctx
, GLclampd d
)
256 mgaContextPtr mmesa
= MGA_CONTEXT(ctx
);
258 /* Select the Z depth. The ~ is used because the _MASK values in the
259 * MGA driver are used to mask OFF the selected bits. In this case,
260 * we want to mask off everything except the MA_zwidth bits.
262 switch (mmesa
->setup
.maccess
& ~MA_zwidth_MASK
) {
263 case MA_zwidth_16
: mmesa
->ClearDepth
= d
* 0x0000ffff; break;
264 case MA_zwidth_24
: mmesa
->ClearDepth
= d
* 0xffffff00; break;
265 case MA_zwidth_32
: mmesa
->ClearDepth
= d
* 0xffffffff; break;
271 /* =============================================================
276 static void mgaDDFogfv(GLcontext
*ctx
, GLenum pname
, const GLfloat
*param
)
278 mgaContextPtr mmesa
= MGA_CONTEXT(ctx
);
280 if (pname
== GL_FOG_COLOR
) {
281 GLuint color
= PACK_COLOR_888((GLubyte
)(ctx
->Fog
.Color
[0]*255.0F
),
282 (GLubyte
)(ctx
->Fog
.Color
[1]*255.0F
),
283 (GLubyte
)(ctx
->Fog
.Color
[2]*255.0F
));
285 MGA_STATECHANGE(mmesa
, MGA_UPLOAD_CONTEXT
);
286 mmesa
->setup
.fogcolor
= color
;
291 /* =============================================================
296 void mgaUpdateClipping(const GLcontext
*ctx
)
298 mgaContextPtr mmesa
= MGA_CONTEXT(ctx
);
300 if (mmesa
->driDrawable
)
302 int x1
= mmesa
->driDrawable
->x
+ ctx
->Scissor
.X
;
303 int y1
= mmesa
->driDrawable
->y
+ mmesa
->driDrawable
->h
304 - (ctx
->Scissor
.Y
+ ctx
->Scissor
.Height
);
305 int x2
= x1
+ ctx
->Scissor
.Width
- 1;
306 int y2
= y1
+ ctx
->Scissor
.Height
- 1;
313 mmesa
->scissor_rect
.x1
= x1
;
314 mmesa
->scissor_rect
.y1
= y1
;
315 mmesa
->scissor_rect
.x2
= x2
;
316 mmesa
->scissor_rect
.y2
= y2
;
318 mmesa
->dirty
|= MGA_UPLOAD_CLIPRECTS
;
323 static void mgaDDScissor( GLcontext
*ctx
, GLint x
, GLint y
,
324 GLsizei w
, GLsizei h
)
326 if ( ctx
->Scissor
.Enabled
) {
327 FLUSH_BATCH( MGA_CONTEXT(ctx
) ); /* don't pipeline cliprect changes */
328 mgaUpdateClipping( ctx
);
333 /* =============================================================
338 #define _CULL_DISABLE 0
339 #define _CULL_NEGATIVE ((1<<11)|(1<<5)|(1<<16))
340 #define _CULL_POSITIVE (1<<11)
342 static void mgaDDCullFaceFrontFace(GLcontext
*ctx
, GLenum unused
)
344 mgaContextPtr mmesa
= MGA_CONTEXT(ctx
);
347 FLUSH_BATCH( mmesa
);
348 if (ctx
->Polygon
.CullFlag
&&
349 ctx
->Polygon
.CullFaceMode
!= GL_FRONT_AND_BACK
)
351 mmesa
->hw
.cull
= _CULL_NEGATIVE
;
353 if (ctx
->Polygon
.CullFaceMode
== GL_FRONT
)
354 mmesa
->hw
.cull
^= (_CULL_POSITIVE
^ _CULL_NEGATIVE
);
356 if (ctx
->Polygon
.FrontFace
!= GL_CCW
)
357 mmesa
->hw
.cull
^= (_CULL_POSITIVE
^ _CULL_NEGATIVE
);
359 mmesa
->hw
.cull_dualtex
= mmesa
->hw
.cull
^
360 (_CULL_POSITIVE
^ _CULL_NEGATIVE
); /* warp bug? */
363 mmesa
->hw
.cull
= _CULL_DISABLE
;
364 mmesa
->hw
.cull_dualtex
= _CULL_DISABLE
;
367 mmesa
->dirty
|= MGA_UPLOAD_CONTEXT
;
371 /* =============================================================
375 static void mgaDDColorMask(GLcontext
*ctx
,
376 GLboolean r
, GLboolean g
,
377 GLboolean b
, GLboolean a
)
379 mgaContextPtr mmesa
= MGA_CONTEXT( ctx
);
380 mgaScreenPrivate
*mgaScreen
= mmesa
->mgaScreen
;
383 GLuint mask
= mgaPackColor(mgaScreen
->cpp
,
384 ctx
->Color
.ColorMask
[RCOMP
],
385 ctx
->Color
.ColorMask
[GCOMP
],
386 ctx
->Color
.ColorMask
[BCOMP
],
387 ctx
->Color
.ColorMask
[ACOMP
]);
389 if (mgaScreen
->cpp
== 2)
390 mask
= mask
| (mask
<< 16);
392 if (mmesa
->setup
.plnwt
!= mask
) {
393 MGA_STATECHANGE( mmesa
, MGA_UPLOAD_CONTEXT
);
394 mmesa
->setup
.plnwt
= mask
;
399 /* =============================================================
403 static int mgaStipples
[16] = {
404 0xffff1, /* See above note */
423 * The MGA supports a subset of possible 4x4 stipples natively, GL
424 * wants 32x32. Fortunately stipple is usually a repeating pattern.
426 * \param ctx GL rendering context to be affected
427 * \param mask Pointer to the 32x32 stipple mask
429 * \note the fully opaque pattern (0xffff) has been disabled in order
430 * to work around a conformance issue.
433 static void mgaDDPolygonStipple( GLcontext
*ctx
, const GLubyte
*mask
)
435 mgaContextPtr mmesa
= MGA_CONTEXT(ctx
);
436 const GLubyte
*m
= mask
;
439 int active
= (ctx
->Polygon
.StippleFlag
&&
440 mmesa
->raster_primitive
== GL_TRIANGLES
);
444 mmesa
->haveHwStipple
= 0;
447 mmesa
->dirty
|= MGA_UPLOAD_CONTEXT
;
448 mmesa
->setup
.dwgctl
&= ~(0xf<<20);
451 p
[0] = mask
[0] & 0xf; p
[0] |= p
[0] << 4;
452 p
[1] = mask
[4] & 0xf; p
[1] |= p
[1] << 4;
453 p
[2] = mask
[8] & 0xf; p
[2] |= p
[2] << 4;
454 p
[3] = mask
[12] & 0xf; p
[3] |= p
[3] << 4;
456 for (k
= 0 ; k
< 8 ; k
++)
457 for (j
= 0 ; j
< 4; j
++)
458 for (i
= 0 ; i
< 4 ; i
++)
463 stipple
= ( ((p
[0] & 0xf) << 0) |
464 ((p
[1] & 0xf) << 4) |
465 ((p
[2] & 0xf) << 8) |
466 ((p
[3] & 0xf) << 12) );
468 for (i
= 0 ; i
< 16 ; i
++)
469 if (mgaStipples
[i
] == stipple
) {
470 mmesa
->poly_stipple
= i
<<20;
471 mmesa
->haveHwStipple
= 1;
476 mmesa
->setup
.dwgctl
&= ~(0xf<<20);
477 mmesa
->setup
.dwgctl
|= mmesa
->poly_stipple
;
482 /* =============================================================
483 * Rendering attributes
485 * We really don't want to recalculate all this every time we bind a
486 * texture. These things shouldn't change all that often, so it makes
487 * sense to break them out of the core texture state update routines.
490 static void updateSpecularLighting( GLcontext
*ctx
)
492 mgaContextPtr mmesa
= MGA_CONTEXT(ctx
);
495 specen
= (ctx
->Light
.Model
.ColorControl
== GL_SEPARATE_SPECULAR_COLOR
&&
496 ctx
->Light
.Enabled
) ? TMC_specen_enable
: 0;
498 if ( specen
!= mmesa
->hw
.specen
) {
499 mmesa
->hw
.specen
= specen
;
500 mmesa
->dirty
|= MGA_UPLOAD_TEX0
| MGA_UPLOAD_TEX1
;
502 mgaChooseVertexState( ctx
);
507 /* =============================================================
512 static void mgaDDLightModelfv(GLcontext
*ctx
, GLenum pname
,
513 const GLfloat
*param
)
515 if (pname
== GL_LIGHT_MODEL_COLOR_CONTROL
) {
516 FLUSH_BATCH( MGA_CONTEXT(ctx
) );
517 updateSpecularLighting( ctx
);
522 static void mgaDDShadeModel(GLcontext
*ctx
, GLenum mode
)
524 /* FIXME: This used to FLUSH_BATCH and set MGA_NEW_TEXTURE in new_state,
525 * FIXME: so I'm not sure what to do here now.
530 /* =============================================================
535 static void mgaDDStencilFunc(GLcontext
*ctx
, GLenum func
, GLint ref
,
538 mgaContextPtr mmesa
= MGA_CONTEXT(ctx
);
542 stencil
= (ref
<< S_sref_SHIFT
) | (mask
<< S_smsk_SHIFT
);
546 stencilctl
= SC_smode_snever
;
549 stencilctl
= SC_smode_slt
;
552 stencilctl
= SC_smode_slte
;
555 stencilctl
= SC_smode_sgt
;
558 stencilctl
= SC_smode_sgte
;
561 stencilctl
= SC_smode_sne
;
564 stencilctl
= SC_smode_se
;
568 stencilctl
= SC_smode_salways
;
572 FLUSH_BATCH( mmesa
);
573 mmesa
->hw
.stencil
&= (S_sref_MASK
& S_smsk_MASK
);
574 mmesa
->hw
.stencil
|= stencil
;
575 mmesa
->hw
.stencilctl
&= SC_smode_MASK
;
576 mmesa
->hw
.stencilctl
|= stencilctl
;
577 mmesa
->dirty
|= MGA_UPLOAD_CONTEXT
;
580 static void mgaDDStencilMask(GLcontext
*ctx
, GLuint mask
)
582 mgaContextPtr mmesa
= MGA_CONTEXT(ctx
);
584 FLUSH_BATCH( mmesa
);
585 mmesa
->hw
.stencil
&= S_swtmsk_MASK
;
586 mmesa
->hw
.stencil
|= (mask
<< S_swtmsk_SHIFT
);
587 mmesa
->dirty
|= MGA_UPLOAD_CONTEXT
;
590 static void mgaDDStencilOp(GLcontext
*ctx
, GLenum fail
, GLenum zfail
,
593 mgaContextPtr mmesa
= MGA_CONTEXT(ctx
);
597 switch (ctx
->Stencil
.FailFunc
[0])
600 stencilctl
|= SC_sfailop_keep
;
603 stencilctl
|= SC_sfailop_zero
;
606 stencilctl
|= SC_sfailop_replace
;
609 stencilctl
|= SC_sfailop_incrsat
;
612 stencilctl
|= SC_sfailop_decrsat
;
615 stencilctl
|= SC_sfailop_incr
;
618 stencilctl
|= SC_sfailop_decr
;
621 stencilctl
|= SC_sfailop_invert
;
627 switch (ctx
->Stencil
.ZFailFunc
[0])
630 stencilctl
|= SC_szfailop_keep
;
633 stencilctl
|= SC_szfailop_zero
;
636 stencilctl
|= SC_szfailop_replace
;
639 stencilctl
|= SC_szfailop_incrsat
;
642 stencilctl
|= SC_szfailop_decrsat
;
645 stencilctl
|= SC_szfailop_incr
;
648 stencilctl
|= SC_szfailop_decr
;
651 stencilctl
|= SC_szfailop_invert
;
657 switch (ctx
->Stencil
.ZPassFunc
[0])
660 stencilctl
|= SC_szpassop_keep
;
663 stencilctl
|= SC_szpassop_zero
;
666 stencilctl
|= SC_szpassop_replace
;
669 stencilctl
|= SC_szpassop_incrsat
;
672 stencilctl
|= SC_szpassop_decrsat
;
675 stencilctl
|= SC_szpassop_invert
;
681 FLUSH_BATCH( mmesa
);
682 mmesa
->hw
.stencilctl
&= (SC_sfailop_MASK
& SC_szfailop_MASK
684 mmesa
->hw
.stencilctl
|= stencilctl
;
685 mmesa
->dirty
|= MGA_UPLOAD_CONTEXT
;
689 /* =============================================================
690 * Window position and viewport transformation
693 void mgaCalcViewport( GLcontext
*ctx
)
695 mgaContextPtr mmesa
= MGA_CONTEXT(ctx
);
696 const GLfloat
*v
= ctx
->Viewport
._WindowMap
.m
;
697 GLfloat
*m
= mmesa
->hw_viewport
;
699 /* See also mga_translate_vertex.
701 m
[MAT_SX
] = v
[MAT_SX
];
702 m
[MAT_TX
] = v
[MAT_TX
] + mmesa
->drawX
+ SUBPIXEL_X
;
703 m
[MAT_SY
] = - v
[MAT_SY
];
704 m
[MAT_TY
] = - v
[MAT_TY
] + mmesa
->driDrawable
->h
+ mmesa
->drawY
+ SUBPIXEL_Y
;
705 m
[MAT_SZ
] = v
[MAT_SZ
] * mmesa
->depth_scale
;
706 m
[MAT_TZ
] = v
[MAT_TZ
] * mmesa
->depth_scale
;
708 mmesa
->SetupNewInputs
= ~0;
711 static void mgaViewport( GLcontext
*ctx
,
713 GLsizei width
, GLsizei height
)
715 mgaCalcViewport( ctx
);
718 static void mgaDepthRange( GLcontext
*ctx
,
719 GLclampd nearval
, GLclampd farval
)
721 mgaCalcViewport( ctx
);
725 /* =============================================================
729 static void mgaDDClearColor(GLcontext
*ctx
,
730 const GLfloat color
[4] )
732 mgaContextPtr mmesa
= MGA_CONTEXT(ctx
);
734 CLAMPED_FLOAT_TO_UBYTE(c
[0], color
[0]);
735 CLAMPED_FLOAT_TO_UBYTE(c
[1], color
[1]);
736 CLAMPED_FLOAT_TO_UBYTE(c
[2], color
[2]);
737 CLAMPED_FLOAT_TO_UBYTE(c
[3], color
[3]);
739 mmesa
->ClearColor
= mgaPackColor( mmesa
->mgaScreen
->cpp
,
740 c
[0], c
[1], c
[2], c
[3]);
744 /* Fallback to swrast for select and feedback.
746 static void mgaRenderMode( GLcontext
*ctx
, GLenum mode
)
748 FALLBACK( ctx
, MGA_FALLBACK_RENDERMODE
, (mode
!= GL_RENDER
) );
752 static void mgaDDLogicOp( GLcontext
*ctx
, GLenum opcode
)
754 mgaContextPtr mmesa
= MGA_CONTEXT( ctx
);
756 FLUSH_BATCH( mmesa
);
757 #if defined(ACCEL_ROP)
758 mmesa
->hw
.rop
= mgarop_NoBLK
[ opcode
& 0x0f ];
759 mmesa
->dirty
|= MGA_UPLOAD_CONTEXT
;
761 FALLBACK( ctx
, MGA_FALLBACK_LOGICOP
,
762 (ctx
->Color
.ColorLogicOpEnabled
&& opcode
!= GL_COPY
) );
767 static void mgaXMesaSetFrontClipRects( mgaContextPtr mmesa
)
769 __DRIdrawablePrivate
*driDrawable
= mmesa
->driDrawable
;
771 if (driDrawable
->numClipRects
== 0) {
772 static XF86DRIClipRectRec zeroareacliprect
= {0,0,0,0};
773 mmesa
->numClipRects
= 1;
774 mmesa
->pClipRects
= &zeroareacliprect
;
776 mmesa
->numClipRects
= driDrawable
->numClipRects
;
777 mmesa
->pClipRects
= driDrawable
->pClipRects
;
779 mmesa
->drawX
= driDrawable
->x
;
780 mmesa
->drawY
= driDrawable
->y
;
782 mmesa
->setup
.dstorg
= mmesa
->drawOffset
;
783 mmesa
->dirty
|= MGA_UPLOAD_CONTEXT
| MGA_UPLOAD_CLIPRECTS
;
787 static void mgaXMesaSetBackClipRects( mgaContextPtr mmesa
)
789 __DRIdrawablePrivate
*driDrawable
= mmesa
->driDrawable
;
791 if (driDrawable
->numBackClipRects
== 0)
793 if (driDrawable
->numClipRects
== 0) {
794 static XF86DRIClipRectRec zeroareacliprect
= {0,0,0,0};
795 mmesa
->numClipRects
= 1;
796 mmesa
->pClipRects
= &zeroareacliprect
;
798 mmesa
->numClipRects
= driDrawable
->numClipRects
;
799 mmesa
->pClipRects
= driDrawable
->pClipRects
;
801 mmesa
->drawX
= driDrawable
->x
;
802 mmesa
->drawY
= driDrawable
->y
;
804 mmesa
->numClipRects
= driDrawable
->numBackClipRects
;
805 mmesa
->pClipRects
= driDrawable
->pBackClipRects
;
806 mmesa
->drawX
= driDrawable
->backX
;
807 mmesa
->drawY
= driDrawable
->backY
;
810 mmesa
->setup
.dstorg
= mmesa
->drawOffset
;
811 mmesa
->dirty
|= MGA_UPLOAD_CONTEXT
| MGA_UPLOAD_CLIPRECTS
;
815 void mgaUpdateRects( mgaContextPtr mmesa
, GLuint buffers
)
817 __DRIdrawablePrivate
*driDrawable
= mmesa
->driDrawable
;
818 MGASAREAPrivPtr sarea
= mmesa
->sarea
;
821 DRI_VALIDATE_DRAWABLE_INFO(mmesa
->driScreen
, driDrawable
);
822 mmesa
->dirty_cliprects
= 0;
824 if (mmesa
->draw_buffer
== MGA_FRONT
)
825 mgaXMesaSetFrontClipRects( mmesa
);
827 mgaXMesaSetBackClipRects( mmesa
);
829 sarea
->req_draw_buffer
= mmesa
->draw_buffer
;
831 mgaUpdateClipping( mmesa
->glCtx
);
832 mgaCalcViewport( mmesa
->glCtx
);
834 mmesa
->dirty
|= MGA_UPLOAD_CLIPRECTS
;
838 static void mgaDDDrawBuffer(GLcontext
*ctx
, GLenum mode
)
840 mgaContextPtr mmesa
= MGA_CONTEXT(ctx
);
842 FLUSH_BATCH( mmesa
);
845 * _DrawDestMask is easier to cope with than <mode>.
847 switch ( ctx
->Color
._DrawDestMask
) {
849 mmesa
->setup
.dstorg
= mmesa
->mgaScreen
->frontOffset
;
850 mmesa
->dirty
|= MGA_UPLOAD_CONTEXT
;
851 mmesa
->draw_buffer
= MGA_FRONT
;
852 mgaXMesaSetFrontClipRects( mmesa
);
853 FALLBACK( ctx
, MGA_FALLBACK_DRAW_BUFFER
, GL_FALSE
);
856 mmesa
->setup
.dstorg
= mmesa
->mgaScreen
->backOffset
;
857 mmesa
->draw_buffer
= MGA_BACK
;
858 mmesa
->dirty
|= MGA_UPLOAD_CONTEXT
;
859 mgaXMesaSetBackClipRects( mmesa
);
860 FALLBACK( ctx
, MGA_FALLBACK_DRAW_BUFFER
, GL_FALSE
);
863 /* GL_NONE or GL_FRONT_AND_BACK or stereo left&right, etc */
864 FALLBACK( ctx
, MGA_FALLBACK_DRAW_BUFFER
, GL_TRUE
);
868 /* We want to update the s/w rast state too so that r200SetBuffer()
871 _swrast_DrawBuffer(ctx
, mode
);
875 static void mgaDDReadBuffer(GLcontext
*ctx
, GLenum mode
)
877 /* nothing, until we implement h/w glRead/CopyPixels or CopyTexImage */
881 /* =============================================================
882 * State enable/disable
886 static void mgaDDEnable(GLcontext
*ctx
, GLenum cap
, GLboolean state
)
888 mgaContextPtr mmesa
= MGA_CONTEXT( ctx
);
892 FLUSH_BATCH( mmesa
);
893 mmesa
->hw
.alpha_func_enable
= (state
) ? ~0 : 0;
896 FLUSH_BATCH( mmesa
);
897 mmesa
->hw
.blend_func_enable
= (state
) ? ~0 : 0;
899 /* For some reason enable(GL_BLEND) affects ColorLogicOpEnabled.
901 FALLBACK( ctx
, MGA_FALLBACK_LOGICOP
,
902 (ctx
->Color
.ColorLogicOpEnabled
&&
903 ctx
->Color
.LogicOp
!= GL_COPY
));
906 FLUSH_BATCH( mmesa
);
907 FALLBACK (ctx
, MGA_FALLBACK_DEPTH
,
908 ctx
->Depth
.Func
== GL_NEVER
&& ctx
->Depth
.Test
);
911 case GL_SCISSOR_TEST
:
912 FLUSH_BATCH( mmesa
);
913 mmesa
->scissor
= state
;
914 mgaUpdateClipping( ctx
);
918 MGA_STATECHANGE( mmesa
, MGA_UPLOAD_CONTEXT
);
919 if (ctx
->Fog
.Enabled
)
920 mmesa
->setup
.maccess
|= MA_fogen_enable
;
922 mmesa
->setup
.maccess
&= ~MA_fogen_enable
;
924 mgaChooseVertexState( ctx
);
927 mgaDDCullFaceFrontFace( ctx
, 0 );
933 case GL_POLYGON_STIPPLE
:
934 if (mmesa
->haveHwStipple
&& mmesa
->raster_primitive
== GL_TRIANGLES
) {
936 mmesa
->dirty
|= MGA_UPLOAD_CONTEXT
;
937 mmesa
->setup
.dwgctl
&= ~(0xf<<20);
939 mmesa
->setup
.dwgctl
|= mmesa
->poly_stipple
;
942 case GL_COLOR_LOGIC_OP
:
943 FLUSH_BATCH( mmesa
);
944 #if !defined(ACCEL_ROP)
945 FALLBACK( ctx
, MGA_FALLBACK_LOGICOP
,
946 (state
&& ctx
->Color
.LogicOp
!= GL_COPY
));
949 case GL_STENCIL_TEST
:
950 FLUSH_BATCH( mmesa
);
951 if (mmesa
->hw_stencil
) {
952 mmesa
->hw
.stencil_enable
= ( state
) ? ~0 : 0;
955 FALLBACK( ctx
, MGA_FALLBACK_STENCIL
, state
);
963 /* =============================================================
966 static void mgaDDPrintDirty( const char *msg
, GLuint state
)
968 fprintf(stderr
, "%s (0x%03x): %s%s%s%s%s%s%s\n",
970 (unsigned int) state
,
971 (state
& MGA_WAIT_AGE
) ? "wait-age " : "",
972 (state
& MGA_UPLOAD_TEX0IMAGE
) ? "upload-tex0-img " : "",
973 (state
& MGA_UPLOAD_TEX1IMAGE
) ? "upload-tex1-img " : "",
974 (state
& MGA_UPLOAD_CONTEXT
) ? "upload-ctx " : "",
975 (state
& MGA_UPLOAD_TEX0
) ? "upload-tex0 " : "",
976 (state
& MGA_UPLOAD_TEX1
) ? "upload-tex1 " : "",
977 (state
& MGA_UPLOAD_PIPE
) ? "upload-pipe " : ""
981 /* Push the state into the sarea and/or texture memory.
983 void mgaEmitHwStateLocked( mgaContextPtr mmesa
)
985 MGASAREAPrivPtr sarea
= mmesa
->sarea
;
986 GLcontext
* ctx
= mmesa
->glCtx
;
988 if (MGA_DEBUG
& DEBUG_VERBOSE_MSG
)
989 mgaDDPrintDirty( __FUNCTION__
, mmesa
->dirty
);
991 if (mmesa
->dirty
& MGA_UPLOAD_CONTEXT
) {
992 mmesa
->setup
.wflag
= _CULL_DISABLE
;
993 if (mmesa
->raster_primitive
== GL_TRIANGLES
) {
994 if ((ctx
->Texture
.Unit
[0]._ReallyEnabled
== TEXTURE_2D_BIT
&&
995 ctx
->Texture
.Unit
[1]._ReallyEnabled
== TEXTURE_2D_BIT
)) {
996 mmesa
->setup
.wflag
= mmesa
->hw
.cull_dualtex
;
999 mmesa
->setup
.wflag
= mmesa
->hw
.cull
;
1003 mmesa
->setup
.stencil
= mmesa
->hw
.stencil
1004 & mmesa
->hw
.stencil_enable
;
1005 mmesa
->setup
.stencilctl
= mmesa
->hw
.stencilctl
1006 & mmesa
->hw
.stencil_enable
;
1008 /* If depth testing is not enabled, then use the no Z-compare / no
1009 * Z-write mode. Otherwise, use whatever is set in hw.zmode.
1011 mmesa
->setup
.dwgctl
&= (DC_zmode_MASK
& DC_atype_MASK
);
1012 mmesa
->setup
.dwgctl
|= (ctx
->Depth
.Test
)
1013 ? mmesa
->hw
.zmode
: (DC_zmode_nozcmp
| DC_atype_i
);
1015 #if defined(ACCEL_ROP)
1016 mmesa
->setup
.dwgctl
&= DC_bop_MASK
;
1017 mmesa
->setup
.dwgctl
|= (ctx
->Color
.ColorLogicOpEnabled
)
1018 ? mmesa
->hw
.rop
: mgarop_NoBLK
[ GL_COPY
& 0x0f ];
1021 mmesa
->setup
.alphactrl
&= AC_src_MASK
& AC_dst_MASK
& AC_atmode_MASK
1022 & AC_atref_MASK
& AC_alphasel_MASK
;
1023 mmesa
->setup
.alphactrl
|=
1024 ((mmesa
->hw
.alpha_func
& mmesa
->hw
.alpha_func_enable
)
1025 | ((mmesa
->hw
.blend_func
& mmesa
->hw
.blend_func_enable
)
1026 | ((AC_src_one
| AC_dst_zero
) & ~mmesa
->hw
.blend_func_enable
))
1027 | mmesa
->hw
.alpha_sel
1028 | (AC_amode_alpha_channel
1029 | AC_astipple_disable
1031 | AC_atmode_noacmp
));
1033 memcpy( &sarea
->ContextState
, &mmesa
->setup
, sizeof(mmesa
->setup
));
1036 if ((mmesa
->dirty
& MGA_UPLOAD_TEX0
) && mmesa
->CurrentTexObj
[0]) {
1037 mmesa
->CurrentTexObj
[0]->setup
.texctl2
&= ~TMC_specen_enable
;
1038 mmesa
->CurrentTexObj
[0]->setup
.texctl2
|= mmesa
->hw
.specen
;
1040 memcpy(&sarea
->TexState
[0],
1041 &mmesa
->CurrentTexObj
[0]->setup
,
1042 sizeof(sarea
->TexState
[0]));
1045 if ((mmesa
->dirty
& MGA_UPLOAD_TEX1
) && mmesa
->CurrentTexObj
[1]) {
1046 mmesa
->CurrentTexObj
[1]->setup
.texctl2
&= ~TMC_specen_enable
;
1047 mmesa
->CurrentTexObj
[1]->setup
.texctl2
|= mmesa
->hw
.specen
;
1049 memcpy(&sarea
->TexState
[1],
1050 &mmesa
->CurrentTexObj
[1]->setup
,
1051 sizeof(sarea
->TexState
[1]));
1054 if ( (sarea
->TexState
[0].texctl2
& TMC_borderen_MASK
) !=
1055 (sarea
->TexState
[1].texctl2
& TMC_borderen_MASK
) ) {
1056 const int borderen
= sarea
->TexState
[1].texctl2
& ~TMC_borderen_MASK
;
1058 memcpy( &sarea
->TexState
[1], &sarea
->TexState
[0],
1059 sizeof(sarea
->TexState
[0]) );
1060 sarea
->TexState
[1].texctl2
|= borderen
;
1061 mmesa
->dirty
|= MGA_UPLOAD_TEX1
|MGA_UPLOAD_TEX0
;
1064 if (mmesa
->dirty
& MGA_UPLOAD_PIPE
) {
1065 /* mmesa->sarea->wacceptseq = mmesa->hw_primitive; */
1066 mmesa
->sarea
->WarpPipe
= mmesa
->vertex_format
;
1067 mmesa
->sarea
->vertsize
= mmesa
->vertex_size
;
1070 mmesa
->sarea
->dirty
|= mmesa
->dirty
;
1071 mmesa
->dirty
&= MGA_UPLOAD_CLIPRECTS
;
1073 /* This is a bit of a hack but seems to be the best place to ensure
1074 * that separate specular is disabled when not needed.
1076 if (ctx
->Texture
._EnabledUnits
== 0 ||
1077 !ctx
->Light
.Enabled
||
1078 ctx
->Light
.Model
.ColorControl
== GL_SINGLE_COLOR
) {
1079 sarea
->TexState
[0].texctl2
&= ~TMC_specen_enable
;
1080 sarea
->TexState
[1].texctl2
&= ~TMC_specen_enable
;
1085 /* =============================================================
1089 static void mgaDDValidateState( GLcontext
*ctx
)
1091 mgaContextPtr mmesa
= MGA_CONTEXT( ctx
);
1092 int new_state
= mmesa
->NewGLState
;
1095 FLUSH_BATCH( mmesa
);
1097 if (mmesa
->NewGLState
& _MGA_NEW_RASTERSETUP
) {
1098 mgaChooseVertexState( ctx
);
1101 if (mmesa
->NewGLState
& _MGA_NEW_RENDERSTATE
) {
1102 mgaChooseRenderState( ctx
);
1105 if (new_state
& _NEW_TEXTURE
) {
1106 mgaUpdateTextureState(ctx
);
1109 mmesa
->NewGLState
= 0;
1113 static void mgaDDInvalidateState( GLcontext
*ctx
, GLuint new_state
)
1115 _swrast_InvalidateState( ctx
, new_state
);
1116 _swsetup_InvalidateState( ctx
, new_state
);
1117 _ac_InvalidateState( ctx
, new_state
);
1118 _tnl_InvalidateState( ctx
, new_state
);
1119 MGA_CONTEXT(ctx
)->NewGLState
|= new_state
;
1123 static void mgaRunPipeline( GLcontext
*ctx
)
1125 mgaContextPtr mmesa
= MGA_CONTEXT(ctx
);
1127 if (mmesa
->NewGLState
) {
1128 mgaDDValidateState( ctx
);
1132 mgaEmitHwStateLocked( mmesa
);
1135 _tnl_run_pipeline( ctx
);
1139 void mgaInitState( mgaContextPtr mmesa
)
1141 mgaScreenPrivate
*mgaScreen
= mmesa
->mgaScreen
;
1142 GLcontext
*ctx
= mmesa
->glCtx
;
1144 if (ctx
->Visual
.doubleBufferMode
) {
1145 /* use back buffer by default */
1146 mmesa
->draw_buffer
= MGA_BACK
;
1147 mmesa
->drawOffset
= mmesa
->mgaScreen
->backOffset
;
1148 mmesa
->readOffset
= mmesa
->mgaScreen
->backOffset
;
1149 mmesa
->setup
.dstorg
= mgaScreen
->backOffset
;
1151 /* use front buffer by default */
1152 mmesa
->draw_buffer
= MGA_FRONT
;
1153 mmesa
->drawOffset
= mmesa
->mgaScreen
->frontOffset
;
1154 mmesa
->readOffset
= mmesa
->mgaScreen
->frontOffset
;
1155 mmesa
->setup
.dstorg
= mgaScreen
->frontOffset
;
1158 mmesa
->setup
.maccess
= (MA_memreset_disable
|
1160 MA_tlutload_disable
|
1161 MA_nodither_disable
|
1164 switch (mmesa
->mgaScreen
->cpp
) {
1166 mmesa
->setup
.maccess
|= MA_pwidth_16
;
1169 mmesa
->setup
.maccess
|= MA_pwidth_32
;
1172 fprintf( stderr
, "Error: unknown cpp %d, exiting...\n",
1173 mmesa
->mgaScreen
->cpp
);
1177 switch (mmesa
->glCtx
->Visual
.depthBits
) {
1179 mmesa
->setup
.maccess
|= MA_zwidth_16
;
1182 mmesa
->setup
.maccess
|= MA_zwidth_24
;
1185 mmesa
->setup
.maccess
|= MA_zwidth_32
;
1189 mmesa
->hw
.zmode
= DC_zmode_zlt
| DC_atype_zi
;
1190 mmesa
->hw
.stencil
= (0x0ff << S_smsk_SHIFT
) | (0x0ff << S_swtmsk_SHIFT
);
1191 mmesa
->hw
.stencilctl
= SC_smode_salways
| SC_sfailop_keep
1192 | SC_szfailop_keep
| SC_szpassop_keep
;
1193 mmesa
->hw
.stencil_enable
= 0;
1194 mmesa
->hw
.cull
= _CULL_NEGATIVE
;
1195 mmesa
->hw
.cull_dualtex
= _CULL_POSITIVE
;
1196 mmesa
->hw
.specen
= 0;
1198 mmesa
->setup
.dwgctl
= (DC_opcod_trap
|
1202 DC_sgnzero_disable
|
1203 DC_shftzero_enable
|
1204 (0xC << DC_bop_SHIFT
) |
1205 (0x0 << DC_trans_SHIFT
) |
1206 DC_bltmod_bmonolef
|
1207 DC_pattern_disable
|
1209 DC_clipdis_disable
);
1212 mmesa
->setup
.plnwt
= ~0;
1213 mmesa
->setup
.alphactrl
= ( AC_src_one
|
1216 AC_astipple_disable
|
1219 AC_alphasel_fromtex
);
1221 mmesa
->setup
.fogcolor
= PACK_COLOR_888((GLubyte
)(ctx
->Fog
.Color
[0]*255.0F
),
1222 (GLubyte
)(ctx
->Fog
.Color
[1]*255.0F
),
1223 (GLubyte
)(ctx
->Fog
.Color
[2]*255.0F
));
1225 mmesa
->setup
.wflag
= 0;
1226 mmesa
->setup
.tdualstage0
= 0;
1227 mmesa
->setup
.tdualstage1
= 0;
1228 mmesa
->setup
.fcol
= 0;
1229 mmesa
->dirty
|= MGA_UPLOAD_CONTEXT
;
1233 void mgaDDInitStateFuncs( GLcontext
*ctx
)
1235 ctx
->Driver
.UpdateState
= mgaDDInvalidateState
;
1236 ctx
->Driver
.Enable
= mgaDDEnable
;
1237 ctx
->Driver
.LightModelfv
= mgaDDLightModelfv
;
1238 ctx
->Driver
.AlphaFunc
= mgaDDAlphaFunc
;
1239 ctx
->Driver
.BlendEquation
= mgaDDBlendEquation
;
1240 ctx
->Driver
.BlendFunc
= mgaDDBlendFunc
;
1241 ctx
->Driver
.BlendFuncSeparate
= mgaDDBlendFuncSeparate
;
1242 ctx
->Driver
.DepthFunc
= mgaDDDepthFunc
;
1243 ctx
->Driver
.DepthMask
= mgaDDDepthMask
;
1244 ctx
->Driver
.Fogfv
= mgaDDFogfv
;
1245 ctx
->Driver
.Scissor
= mgaDDScissor
;
1246 ctx
->Driver
.ShadeModel
= mgaDDShadeModel
;
1247 ctx
->Driver
.CullFace
= mgaDDCullFaceFrontFace
;
1248 ctx
->Driver
.FrontFace
= mgaDDCullFaceFrontFace
;
1249 ctx
->Driver
.ColorMask
= mgaDDColorMask
;
1251 ctx
->Driver
.DrawBuffer
= mgaDDDrawBuffer
;
1252 ctx
->Driver
.ReadBuffer
= mgaDDReadBuffer
;
1253 ctx
->Driver
.ClearColor
= mgaDDClearColor
;
1254 ctx
->Driver
.ClearDepth
= mgaDDClearDepth
;
1255 ctx
->Driver
.LogicOpcode
= mgaDDLogicOp
;
1257 ctx
->Driver
.PolygonStipple
= mgaDDPolygonStipple
;
1259 ctx
->Driver
.StencilFunc
= mgaDDStencilFunc
;
1260 ctx
->Driver
.StencilMask
= mgaDDStencilMask
;
1261 ctx
->Driver
.StencilOp
= mgaDDStencilOp
;
1263 ctx
->Driver
.DepthRange
= mgaDepthRange
;
1264 ctx
->Driver
.Viewport
= mgaViewport
;
1265 ctx
->Driver
.RenderMode
= mgaRenderMode
;
1267 ctx
->Driver
.ClearIndex
= 0;
1268 ctx
->Driver
.IndexMask
= 0;
1270 /* Swrast hooks for imaging extensions:
1272 ctx
->Driver
.CopyColorTable
= _swrast_CopyColorTable
;
1273 ctx
->Driver
.CopyColorSubTable
= _swrast_CopyColorSubTable
;
1274 ctx
->Driver
.CopyConvolutionFilter1D
= _swrast_CopyConvolutionFilter1D
;
1275 ctx
->Driver
.CopyConvolutionFilter2D
= _swrast_CopyConvolutionFilter2D
;
1277 TNL_CONTEXT(ctx
)->Driver
.RunPipeline
= mgaRunPipeline
;