1 /* $XFree86: xc/lib/GL/mesa/src/drv/r128/r128_state.c,v 1.11 2002/10/30 12:51:39 alanh Exp $ */
2 /**************************************************************************
4 Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc.,
8 Permission is hereby granted, free of charge, to any person obtaining a
9 copy of this software and associated documentation files (the "Software"),
10 to deal in the Software without restriction, including without limitation
11 on the rights to use, copy, modify, merge, publish, distribute, sub
12 license, and/or sell copies of the Software, and to permit persons to whom
13 the Software is furnished to do so, subject to the following conditions:
15 The above copyright notice and this permission notice (including the next
16 paragraph) shall be included in all copies or substantial portions of the
19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
22 ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
23 DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
24 OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
25 USE OR OTHER DEALINGS IN THE SOFTWARE.
27 **************************************************************************/
31 * Gareth Hughes <gareth@valinux.com>
32 * Kevin E. Martin <martin@valinux.com>
33 * Keith Whitwell <keith@tungstengraphics.com>
37 #include "r128_context.h"
38 #include "r128_state.h"
39 #include "r128_ioctl.h"
40 #include "r128_tris.h"
47 #include "swrast/swrast.h"
48 #include "array_cache/acache.h"
50 #include "swrast_setup/swrast_setup.h"
52 #include "tnl/t_pipeline.h"
54 #include "drirenderbuffer.h"
57 /* =============================================================
63 * Calculate the hardware blend factor setting. This same function is used
64 * for source and destination of both alpha and RGB.
67 * The hardware register value for the specified blend factor. This value
68 * will need to be shifted into the correct position for either source or
72 * Since the two cases where source and destination are handled differently
73 * are essentially error cases, they should never happen. Determine if these
74 * cases can be removed.
76 static int blend_factor( r128ContextPtr rmesa
, GLenum factor
, GLboolean is_src
)
82 func
= R128_ALPHA_BLEND_ZERO
;
85 func
= R128_ALPHA_BLEND_ONE
;
89 func
= R128_ALPHA_BLEND_SRCCOLOR
;
91 case GL_ONE_MINUS_SRC_COLOR
:
92 func
= R128_ALPHA_BLEND_INVSRCCOLOR
;
95 func
= R128_ALPHA_BLEND_SRCALPHA
;
97 case GL_ONE_MINUS_SRC_ALPHA
:
98 func
= R128_ALPHA_BLEND_INVSRCALPHA
;
100 case GL_SRC_ALPHA_SATURATE
:
101 func
= (is_src
) ? R128_ALPHA_BLEND_SAT
: R128_ALPHA_BLEND_ZERO
;
105 func
= R128_ALPHA_BLEND_DSTCOLOR
;
107 case GL_ONE_MINUS_DST_COLOR
:
108 func
= R128_ALPHA_BLEND_INVDSTCOLOR
;
111 func
= R128_ALPHA_BLEND_DSTALPHA
;
113 case GL_ONE_MINUS_DST_ALPHA
:
114 func
= R128_ALPHA_BLEND_INVDSTALPHA
;
117 case GL_CONSTANT_COLOR
:
118 case GL_ONE_MINUS_CONSTANT_COLOR
:
119 case GL_CONSTANT_ALPHA
:
120 case GL_ONE_MINUS_CONSTANT_ALPHA
:
122 FALLBACK( rmesa
, R128_FALLBACK_BLEND_FUNC
, GL_TRUE
);
123 func
= (is_src
) ? R128_ALPHA_BLEND_ONE
: R128_ALPHA_BLEND_ZERO
;
131 static void r128UpdateAlphaMode( GLcontext
*ctx
)
133 r128ContextPtr rmesa
= R128_CONTEXT(ctx
);
134 GLuint a
= rmesa
->setup
.misc_3d_state_cntl_reg
;
135 GLuint t
= rmesa
->setup
.tex_cntl_c
;
137 if ( ctx
->Color
.AlphaEnabled
) {
140 CLAMPED_FLOAT_TO_UBYTE(ref
, ctx
->Color
.AlphaRef
);
142 a
&= ~(R128_ALPHA_TEST_MASK
| R128_REF_ALPHA_MASK
);
144 switch ( ctx
->Color
.AlphaFunc
) {
146 a
|= R128_ALPHA_TEST_NEVER
;
149 a
|= R128_ALPHA_TEST_LESS
;
152 a
|= R128_ALPHA_TEST_LESSEQUAL
;
155 a
|= R128_ALPHA_TEST_EQUAL
;
158 a
|= R128_ALPHA_TEST_GREATEREQUAL
;
161 a
|= R128_ALPHA_TEST_GREATER
;
164 a
|= R128_ALPHA_TEST_NEQUAL
;
167 a
|= R128_ALPHA_TEST_ALWAYS
;
171 a
|= ref
& R128_REF_ALPHA_MASK
;
172 t
|= R128_ALPHA_TEST_ENABLE
;
174 t
&= ~R128_ALPHA_TEST_ENABLE
;
177 FALLBACK( rmesa
, R128_FALLBACK_BLEND_FUNC
, GL_FALSE
);
179 if ( ctx
->Color
.BlendEnabled
) {
180 a
&= ~((R128_ALPHA_BLEND_MASK
<< R128_ALPHA_BLEND_SRC_SHIFT
) |
181 (R128_ALPHA_BLEND_MASK
<< R128_ALPHA_BLEND_DST_SHIFT
)
182 | R128_ALPHA_COMB_FCN_MASK
);
184 a
|= blend_factor( rmesa
, ctx
->Color
.BlendSrcRGB
, GL_TRUE
)
185 << R128_ALPHA_BLEND_SRC_SHIFT
;
186 a
|= blend_factor( rmesa
, ctx
->Color
.BlendDstRGB
, GL_FALSE
)
187 << R128_ALPHA_BLEND_DST_SHIFT
;
189 switch (ctx
->Color
.BlendEquationRGB
) {
191 a
|= R128_ALPHA_COMB_ADD_CLAMP
;
193 case GL_FUNC_SUBTRACT
:
194 a
|= R128_ALPHA_COMB_SUB_SRC_DST_CLAMP
;
197 FALLBACK( rmesa
, R128_FALLBACK_BLEND_EQ
, GL_TRUE
);
200 t
|= R128_ALPHA_ENABLE
;
202 t
&= ~R128_ALPHA_ENABLE
;
205 if ( rmesa
->setup
.misc_3d_state_cntl_reg
!= a
) {
206 rmesa
->setup
.misc_3d_state_cntl_reg
= a
;
207 rmesa
->dirty
|= R128_UPLOAD_CONTEXT
| R128_UPLOAD_MASKS
;
209 if ( rmesa
->setup
.tex_cntl_c
!= t
) {
210 rmesa
->setup
.tex_cntl_c
= t
;
211 rmesa
->dirty
|= R128_UPLOAD_CONTEXT
| R128_UPLOAD_MASKS
;
215 static void r128DDAlphaFunc( GLcontext
*ctx
, GLenum func
, GLfloat ref
)
217 r128ContextPtr rmesa
= R128_CONTEXT(ctx
);
219 FLUSH_BATCH( rmesa
);
220 rmesa
->new_state
|= R128_NEW_ALPHA
;
223 static void r128DDBlendEquationSeparate( GLcontext
*ctx
,
224 GLenum modeRGB
, GLenum modeA
)
226 r128ContextPtr rmesa
= R128_CONTEXT(ctx
);
228 assert( modeRGB
== modeA
);
229 FLUSH_BATCH( rmesa
);
231 /* BlendEquation sets ColorLogicOpEnabled in an unexpected
234 FALLBACK( R128_CONTEXT(ctx
), R128_FALLBACK_LOGICOP
,
235 (ctx
->Color
.ColorLogicOpEnabled
&&
236 ctx
->Color
.LogicOp
!= GL_COPY
));
238 /* Can only do blend addition, not min, max, subtract, etc. */
239 FALLBACK( R128_CONTEXT(ctx
), R128_FALLBACK_BLEND_EQ
,
240 (modeRGB
!= GL_FUNC_ADD
) && (modeRGB
!= GL_FUNC_SUBTRACT
));
242 rmesa
->new_state
|= R128_NEW_ALPHA
;
245 static void r128DDBlendFuncSeparate( GLcontext
*ctx
,
246 GLenum sfactorRGB
, GLenum dfactorRGB
,
247 GLenum sfactorA
, GLenum dfactorA
)
249 r128ContextPtr rmesa
= R128_CONTEXT(ctx
);
251 FLUSH_BATCH( rmesa
);
252 rmesa
->new_state
|= R128_NEW_ALPHA
;
256 /* =============================================================
260 static void r128UpdateZMode( GLcontext
*ctx
)
262 r128ContextPtr rmesa
= R128_CONTEXT(ctx
);
263 GLuint z
= rmesa
->setup
.z_sten_cntl_c
;
264 GLuint t
= rmesa
->setup
.tex_cntl_c
;
266 if ( ctx
->Depth
.Test
) {
267 z
&= ~R128_Z_TEST_MASK
;
269 switch ( ctx
->Depth
.Func
) {
271 z
|= R128_Z_TEST_NEVER
;
274 z
|= R128_Z_TEST_ALWAYS
;
277 z
|= R128_Z_TEST_LESS
;
280 z
|= R128_Z_TEST_LESSEQUAL
;
283 z
|= R128_Z_TEST_EQUAL
;
286 z
|= R128_Z_TEST_GREATEREQUAL
;
289 z
|= R128_Z_TEST_GREATER
;
292 z
|= R128_Z_TEST_NEQUAL
;
301 if ( ctx
->Depth
.Mask
) {
302 t
|= R128_Z_WRITE_ENABLE
;
304 t
&= ~R128_Z_WRITE_ENABLE
;
307 if ( rmesa
->setup
.z_sten_cntl_c
!= z
) {
308 rmesa
->setup
.z_sten_cntl_c
= z
;
309 rmesa
->dirty
|= R128_UPLOAD_CONTEXT
;
311 if ( rmesa
->setup
.tex_cntl_c
!= t
) {
312 rmesa
->setup
.tex_cntl_c
= t
;
313 rmesa
->dirty
|= R128_UPLOAD_CONTEXT
;
317 static void r128DDDepthFunc( GLcontext
*ctx
, GLenum func
)
319 r128ContextPtr rmesa
= R128_CONTEXT(ctx
);
321 FLUSH_BATCH( rmesa
);
322 rmesa
->new_state
|= R128_NEW_DEPTH
;
325 static void r128DDDepthMask( GLcontext
*ctx
, GLboolean flag
)
327 r128ContextPtr rmesa
= R128_CONTEXT(ctx
);
329 FLUSH_BATCH( rmesa
);
330 rmesa
->new_state
|= R128_NEW_DEPTH
;
333 static void r128DDClearDepth( GLcontext
*ctx
, GLclampd d
)
335 r128ContextPtr rmesa
= R128_CONTEXT(ctx
);
337 switch ( rmesa
->setup
.z_sten_cntl_c
& R128_Z_PIX_WIDTH_MASK
) {
338 case R128_Z_PIX_WIDTH_16
:
339 rmesa
->ClearDepth
= d
* 0x0000ffff;
341 case R128_Z_PIX_WIDTH_24
:
342 rmesa
->ClearDepth
= d
* 0x00ffffff;
344 case R128_Z_PIX_WIDTH_32
:
345 rmesa
->ClearDepth
= d
* 0xffffffff;
351 /* =============================================================
355 static void r128UpdateFogAttrib( GLcontext
*ctx
)
357 r128ContextPtr rmesa
= R128_CONTEXT(ctx
);
358 GLuint t
= rmesa
->setup
.tex_cntl_c
;
362 if ( ctx
->Fog
.Enabled
) {
363 t
|= R128_FOG_ENABLE
;
365 t
&= ~R128_FOG_ENABLE
;
368 c
[0] = FLOAT_TO_UBYTE( ctx
->Fog
.Color
[0] );
369 c
[1] = FLOAT_TO_UBYTE( ctx
->Fog
.Color
[1] );
370 c
[2] = FLOAT_TO_UBYTE( ctx
->Fog
.Color
[2] );
372 col
= r128PackColor( 4, c
[0], c
[1], c
[2], 0 );
374 if ( rmesa
->setup
.fog_color_c
!= col
) {
375 rmesa
->setup
.fog_color_c
= col
;
376 rmesa
->dirty
|= R128_UPLOAD_CONTEXT
;
378 if ( rmesa
->setup
.tex_cntl_c
!= t
) {
379 rmesa
->setup
.tex_cntl_c
= t
;
380 rmesa
->dirty
|= R128_UPLOAD_CONTEXT
;
384 static void r128DDFogfv( GLcontext
*ctx
, GLenum pname
, const GLfloat
*param
)
386 r128ContextPtr rmesa
= R128_CONTEXT(ctx
);
388 FLUSH_BATCH( rmesa
);
389 rmesa
->new_state
|= R128_NEW_FOG
;
393 /* =============================================================
397 static void r128UpdateClipping( GLcontext
*ctx
)
399 r128ContextPtr rmesa
= R128_CONTEXT(ctx
);
401 if ( rmesa
->driDrawable
) {
402 __DRIdrawablePrivate
*drawable
= rmesa
->driDrawable
;
405 int x2
= drawable
->w
- 1;
406 int y2
= drawable
->h
- 1;
408 if ( ctx
->Scissor
.Enabled
) {
409 if ( ctx
->Scissor
.X
> x1
) {
412 if ( drawable
->h
- ctx
->Scissor
.Y
- ctx
->Scissor
.Height
> y1
) {
413 y1
= drawable
->h
- ctx
->Scissor
.Y
- ctx
->Scissor
.Height
;
415 if ( ctx
->Scissor
.X
+ ctx
->Scissor
.Width
- 1 < x2
) {
416 x2
= ctx
->Scissor
.X
+ ctx
->Scissor
.Width
- 1;
418 if ( drawable
->h
- ctx
->Scissor
.Y
- 1 < y2
) {
419 y2
= drawable
->h
- ctx
->Scissor
.Y
- 1;
428 rmesa
->setup
.sc_top_left_c
= ((y1
<< 16) | x1
);
429 rmesa
->setup
.sc_bottom_right_c
= ((y2
<< 16) | x2
);
431 rmesa
->dirty
|= R128_UPLOAD_CONTEXT
;
435 static void r128DDScissor( GLcontext
*ctx
,
436 GLint x
, GLint y
, GLsizei w
, GLsizei h
)
438 r128ContextPtr rmesa
= R128_CONTEXT(ctx
);
440 FLUSH_BATCH( rmesa
);
441 rmesa
->new_state
|= R128_NEW_CLIP
;
445 /* =============================================================
449 static void r128UpdateCull( GLcontext
*ctx
)
451 r128ContextPtr rmesa
= R128_CONTEXT(ctx
);
452 GLuint f
= rmesa
->setup
.pm4_vc_fpu_setup
;
454 f
&= ~R128_FRONT_DIR_MASK
;
456 switch ( ctx
->Polygon
.FrontFace
) {
458 f
|= R128_FRONT_DIR_CW
;
461 f
|= R128_FRONT_DIR_CCW
;
465 f
|= R128_BACKFACE_SOLID
| R128_FRONTFACE_SOLID
;
467 if ( ctx
->Polygon
.CullFlag
) {
468 switch ( ctx
->Polygon
.CullFaceMode
) {
470 f
&= ~R128_FRONTFACE_SOLID
;
473 f
&= ~R128_BACKFACE_SOLID
;
475 case GL_FRONT_AND_BACK
:
476 f
&= ~(R128_BACKFACE_SOLID
|
477 R128_FRONTFACE_SOLID
);
482 if ( 1 || rmesa
->setup
.pm4_vc_fpu_setup
!= f
) {
483 rmesa
->setup
.pm4_vc_fpu_setup
= f
;
484 rmesa
->dirty
|= R128_UPLOAD_CONTEXT
| R128_UPLOAD_SETUP
;
488 static void r128DDCullFace( GLcontext
*ctx
, GLenum mode
)
490 r128ContextPtr rmesa
= R128_CONTEXT(ctx
);
492 FLUSH_BATCH( rmesa
);
493 rmesa
->new_state
|= R128_NEW_CULL
;
496 static void r128DDFrontFace( GLcontext
*ctx
, GLenum mode
)
498 r128ContextPtr rmesa
= R128_CONTEXT(ctx
);
500 FLUSH_BATCH( rmesa
);
501 rmesa
->new_state
|= R128_NEW_CULL
;
505 /* =============================================================
509 static void r128UpdateMasks( GLcontext
*ctx
)
511 r128ContextPtr rmesa
= R128_CONTEXT(ctx
);
513 GLuint mask
= r128PackColor( rmesa
->r128Screen
->cpp
,
514 ctx
->Color
.ColorMask
[RCOMP
],
515 ctx
->Color
.ColorMask
[GCOMP
],
516 ctx
->Color
.ColorMask
[BCOMP
],
517 ctx
->Color
.ColorMask
[ACOMP
] );
519 if ( rmesa
->setup
.plane_3d_mask_c
!= mask
) {
520 rmesa
->setup
.plane_3d_mask_c
= mask
;
521 rmesa
->dirty
|= R128_UPLOAD_CONTEXT
| R128_UPLOAD_MASKS
;
525 static void r128DDColorMask( GLcontext
*ctx
,
526 GLboolean r
, GLboolean g
,
527 GLboolean b
, GLboolean a
)
529 r128ContextPtr rmesa
= R128_CONTEXT(ctx
);
531 FLUSH_BATCH( rmesa
);
532 rmesa
->new_state
|= R128_NEW_MASKS
;
536 /* =============================================================
537 * Rendering attributes
539 * We really don't want to recalculate all this every time we bind a
540 * texture. These things shouldn't change all that often, so it makes
541 * sense to break them out of the core texture state update routines.
544 static void updateSpecularLighting( GLcontext
*ctx
)
546 r128ContextPtr rmesa
= R128_CONTEXT(ctx
);
547 GLuint t
= rmesa
->setup
.tex_cntl_c
;
549 if ( ctx
->Light
.Model
.ColorControl
== GL_SEPARATE_SPECULAR_COLOR
&&
550 ctx
->Light
.Enabled
) {
551 /* XXX separate specular color just doesn't seem to work as it should.
552 * For now, we fall back to s/w rendering whenever separate specular
556 if (ctx
->Light
.ShadeModel
== GL_FLAT
) {
557 /* R128 can't do flat-shaded separate specular */
558 t
&= ~R128_SPEC_LIGHT_ENABLE
;
559 FALLBACK( rmesa
, R128_FALLBACK_SEP_SPECULAR
, GL_TRUE
);
560 /*printf("%s fallback sep spec\n", __FUNCTION__);*/
563 t
|= R128_SPEC_LIGHT_ENABLE
;
564 FALLBACK( rmesa
, R128_FALLBACK_SEP_SPECULAR
, GL_FALSE
);
565 /*printf("%s enable sep spec\n", __FUNCTION__);*/
568 t
&= ~R128_SPEC_LIGHT_ENABLE
;
569 FALLBACK( rmesa
, R128_FALLBACK_SEP_SPECULAR
, GL_TRUE
);
570 /*printf("%s fallback sep spec\n", __FUNCTION__);*/
574 t
&= ~R128_SPEC_LIGHT_ENABLE
;
575 FALLBACK( rmesa
, R128_FALLBACK_SEP_SPECULAR
, GL_FALSE
);
576 /*printf("%s disable sep spec\n", __FUNCTION__);*/
579 if ( rmesa
->setup
.tex_cntl_c
!= t
) {
580 rmesa
->setup
.tex_cntl_c
= t
;
581 rmesa
->dirty
|= R128_UPLOAD_CONTEXT
;
582 rmesa
->dirty
|= R128_UPLOAD_SETUP
;
583 rmesa
->new_state
|= R128_NEW_CONTEXT
;
588 static void r128DDLightModelfv( GLcontext
*ctx
, GLenum pname
,
589 const GLfloat
*param
)
591 r128ContextPtr rmesa
= R128_CONTEXT(ctx
);
593 if ( pname
== GL_LIGHT_MODEL_COLOR_CONTROL
) {
594 FLUSH_BATCH( rmesa
);
595 updateSpecularLighting(ctx
);
599 static void r128DDShadeModel( GLcontext
*ctx
, GLenum mode
)
601 r128ContextPtr rmesa
= R128_CONTEXT(ctx
);
602 GLuint s
= rmesa
->setup
.pm4_vc_fpu_setup
;
604 s
&= ~R128_FPU_COLOR_MASK
;
608 s
|= R128_FPU_COLOR_FLAT
;
611 s
|= R128_FPU_COLOR_GOURAUD
;
617 updateSpecularLighting(ctx
);
619 if ( rmesa
->setup
.pm4_vc_fpu_setup
!= s
) {
620 FLUSH_BATCH( rmesa
);
621 rmesa
->setup
.pm4_vc_fpu_setup
= s
;
623 rmesa
->new_state
|= R128_NEW_CONTEXT
;
624 rmesa
->dirty
|= R128_UPLOAD_SETUP
;
629 /* =============================================================
633 static void r128UpdateWindow( GLcontext
*ctx
)
635 r128ContextPtr rmesa
= R128_CONTEXT(ctx
);
636 int x
= rmesa
->driDrawable
->x
;
637 int y
= rmesa
->driDrawable
->y
;
638 struct gl_renderbuffer
*rb
= ctx
->DrawBuffer
->_ColorDrawBuffers
[0][0];
639 driRenderbuffer
*drb
= (driRenderbuffer
*) rb
;
641 rmesa
->setup
.window_xy_offset
= ((y
<< R128_WINDOW_Y_SHIFT
) |
642 (x
<< R128_WINDOW_X_SHIFT
));
644 rmesa
->setup
.dst_pitch_offset_c
= (((drb
->flippedPitch
/8) << 21) |
645 (drb
->flippedOffset
>> 5));
648 rmesa
->dirty
|= R128_UPLOAD_CONTEXT
| R128_UPLOAD_WINDOW
;
652 /* =============================================================
656 static void r128CalcViewport( GLcontext
*ctx
)
658 r128ContextPtr rmesa
= R128_CONTEXT(ctx
);
659 const GLfloat
*v
= ctx
->Viewport
._WindowMap
.m
;
660 GLfloat
*m
= rmesa
->hw_viewport
;
662 /* See also r128_translate_vertex.
664 m
[MAT_SX
] = v
[MAT_SX
];
665 m
[MAT_TX
] = v
[MAT_TX
] + SUBPIXEL_X
;
666 m
[MAT_SY
] = - v
[MAT_SY
];
667 m
[MAT_TY
] = - v
[MAT_TY
] + rmesa
->driDrawable
->h
+ SUBPIXEL_Y
;
668 m
[MAT_SZ
] = v
[MAT_SZ
] * rmesa
->depth_scale
;
669 m
[MAT_TZ
] = v
[MAT_TZ
] * rmesa
->depth_scale
;
672 static void r128Viewport( GLcontext
*ctx
,
674 GLsizei width
, GLsizei height
)
676 /* update size of Mesa/software ancillary buffers */
677 _mesa_ResizeBuffersMESA();
678 r128CalcViewport( ctx
);
681 static void r128DepthRange( GLcontext
*ctx
,
682 GLclampd nearval
, GLclampd farval
)
684 r128CalcViewport( ctx
);
688 /* =============================================================
692 static void r128DDClearColor( GLcontext
*ctx
,
693 const GLfloat color
[4] )
695 r128ContextPtr rmesa
= R128_CONTEXT(ctx
);
698 CLAMPED_FLOAT_TO_UBYTE(c
[0], color
[0]);
699 CLAMPED_FLOAT_TO_UBYTE(c
[1], color
[1]);
700 CLAMPED_FLOAT_TO_UBYTE(c
[2], color
[2]);
701 CLAMPED_FLOAT_TO_UBYTE(c
[3], color
[3]);
703 rmesa
->ClearColor
= r128PackColor( rmesa
->r128Screen
->cpp
,
704 c
[0], c
[1], c
[2], c
[3] );
707 static void r128DDLogicOpCode( GLcontext
*ctx
, GLenum opcode
)
709 r128ContextPtr rmesa
= R128_CONTEXT(ctx
);
711 if ( ctx
->Color
.ColorLogicOpEnabled
) {
712 FLUSH_BATCH( rmesa
);
714 FALLBACK( rmesa
, R128_FALLBACK_LOGICOP
, opcode
!= GL_COPY
);
718 static void r128DDDrawBuffer( GLcontext
*ctx
, GLenum mode
)
720 r128ContextPtr rmesa
= R128_CONTEXT(ctx
);
722 FLUSH_BATCH( rmesa
);
725 * _ColorDrawBufferMask is easier to cope with than <mode>.
727 switch ( ctx
->DrawBuffer
->_ColorDrawBufferMask
[0] ) {
728 case BUFFER_BIT_FRONT_LEFT
:
729 FALLBACK( rmesa
, R128_FALLBACK_DRAW_BUFFER
, GL_FALSE
);
731 case BUFFER_BIT_BACK_LEFT
:
732 FALLBACK( rmesa
, R128_FALLBACK_DRAW_BUFFER
, GL_FALSE
);
735 /* GL_NONE or GL_FRONT_AND_BACK or stereo left&right, etc */
736 FALLBACK( rmesa
, R128_FALLBACK_DRAW_BUFFER
, GL_TRUE
);
740 rmesa
->new_state
|= R128_NEW_WINDOW
;
743 static void r128DDReadBuffer( GLcontext
*ctx
, GLenum mode
)
745 /* nothing, until we implement h/w glRead/CopyPixels or CopyTexImage */
749 /* =============================================================
753 static void r128DDPolygonStipple( GLcontext
*ctx
, const GLubyte
*mask
)
755 r128ContextPtr rmesa
= R128_CONTEXT(ctx
);
756 GLuint stipple
[32], i
;
757 drm_r128_stipple_t stippleRec
;
759 for (i
= 0; i
< 32; i
++) {
760 stipple
[31 - i
] = ((mask
[i
*4+0] << 24) |
761 (mask
[i
*4+1] << 16) |
766 FLUSH_BATCH( rmesa
);
767 LOCK_HARDWARE( rmesa
);
769 stippleRec
.mask
= stipple
;
770 drmCommandWrite( rmesa
->driFd
, DRM_R128_STIPPLE
,
771 &stippleRec
, sizeof(stippleRec
) );
773 UNLOCK_HARDWARE( rmesa
);
775 rmesa
->new_state
|= R128_NEW_CONTEXT
;
776 rmesa
->dirty
|= R128_UPLOAD_CONTEXT
;
780 /* =============================================================
784 static void r128DDRenderMode( GLcontext
*ctx
, GLenum mode
)
786 r128ContextPtr rmesa
= R128_CONTEXT(ctx
);
787 FALLBACK( rmesa
, R128_FALLBACK_RENDER_MODE
, (mode
!= GL_RENDER
) );
792 /* =============================================================
793 * State enable/disable
796 static void r128DDEnable( GLcontext
*ctx
, GLenum cap
, GLboolean state
)
798 r128ContextPtr rmesa
= R128_CONTEXT(ctx
);
800 if ( R128_DEBUG
& DEBUG_VERBOSE_API
) {
801 fprintf( stderr
, "%s( %s = %s )\n",
802 __FUNCTION__
, _mesa_lookup_enum_by_nr( cap
),
803 state
? "GL_TRUE" : "GL_FALSE" );
808 FLUSH_BATCH( rmesa
);
809 rmesa
->new_state
|= R128_NEW_ALPHA
;
813 FLUSH_BATCH( rmesa
);
814 rmesa
->new_state
|= R128_NEW_ALPHA
;
816 /* For some reason enable(GL_BLEND) affects ColorLogicOpEnabled.
818 FALLBACK( rmesa
, R128_FALLBACK_LOGICOP
,
819 (ctx
->Color
.ColorLogicOpEnabled
&&
820 ctx
->Color
.LogicOp
!= GL_COPY
));
824 FLUSH_BATCH( rmesa
);
825 rmesa
->new_state
|= R128_NEW_CULL
;
829 FLUSH_BATCH( rmesa
);
830 rmesa
->new_state
|= R128_NEW_DEPTH
;
835 GLuint t
= rmesa
->setup
.tex_cntl_c
;
836 FLUSH_BATCH( rmesa
);
838 if ( ctx
->Color
.DitherFlag
) {
839 t
|= R128_DITHER_ENABLE
;
841 t
&= ~R128_DITHER_ENABLE
;
844 if ( rmesa
->setup
.tex_cntl_c
!= t
) {
845 rmesa
->setup
.tex_cntl_c
= t
;
846 rmesa
->dirty
|= R128_UPLOAD_CONTEXT
;
852 FLUSH_BATCH( rmesa
);
853 rmesa
->new_state
|= R128_NEW_FOG
;
856 case GL_COLOR_LOGIC_OP
:
857 FLUSH_BATCH( rmesa
);
858 FALLBACK( rmesa
, R128_FALLBACK_LOGICOP
,
859 state
&& ctx
->Color
.LogicOp
!= GL_COPY
);
863 updateSpecularLighting(ctx
);
866 case GL_SCISSOR_TEST
:
867 FLUSH_BATCH( rmesa
);
868 rmesa
->scissor
= state
;
869 rmesa
->new_state
|= R128_NEW_CLIP
;
872 case GL_STENCIL_TEST
:
873 FLUSH_BATCH( rmesa
);
874 FALLBACK( rmesa
, R128_FALLBACK_STENCIL
, state
);
880 FLUSH_BATCH( rmesa
);
883 case GL_POLYGON_STIPPLE
:
884 if ( rmesa
->render_primitive
== GL_TRIANGLES
) {
885 FLUSH_BATCH( rmesa
);
886 rmesa
->setup
.dp_gui_master_cntl_c
&= ~R128_GMC_BRUSH_NONE
;
888 rmesa
->setup
.dp_gui_master_cntl_c
|=
889 R128_GMC_BRUSH_32x32_MONO_FG_LA
;
891 rmesa
->setup
.dp_gui_master_cntl_c
|=
892 R128_GMC_BRUSH_SOLID_COLOR
;
894 rmesa
->new_state
|= R128_NEW_CONTEXT
;
895 rmesa
->dirty
|= R128_UPLOAD_CONTEXT
;
905 /* =============================================================
906 * State initialization, management
909 static void r128DDPrintDirty( const char *msg
, GLuint state
)
912 "%s: (0x%x) %s%s%s%s%s%s%s%s%s\n",
915 (state
& R128_UPLOAD_CORE
) ? "core, " : "",
916 (state
& R128_UPLOAD_CONTEXT
) ? "context, " : "",
917 (state
& R128_UPLOAD_SETUP
) ? "setup, " : "",
918 (state
& R128_UPLOAD_TEX0
) ? "tex0, " : "",
919 (state
& R128_UPLOAD_TEX1
) ? "tex1, " : "",
920 (state
& R128_UPLOAD_MASKS
) ? "masks, " : "",
921 (state
& R128_UPLOAD_WINDOW
) ? "window, " : "",
922 (state
& R128_UPLOAD_CLIPRECTS
) ? "cliprects, " : "",
923 (state
& R128_REQUIRE_QUIESCENCE
) ? "quiescence, " : "" );
927 * Load the current context's state into the hardware.
929 * NOTE: Be VERY careful about ensuring the context state is marked for
930 * upload, the only place it shouldn't be uploaded is when the setup
931 * state has changed in ReducedPrimitiveChange as this comes right after
934 * Blits of any type should always upload the context and masks after
937 void r128EmitHwStateLocked( r128ContextPtr rmesa
)
939 drm_r128_sarea_t
*sarea
= rmesa
->sarea
;
940 drm_r128_context_regs_t
*regs
= &(rmesa
->setup
);
941 const r128TexObjPtr t0
= rmesa
->CurrentTexObj
[0];
942 const r128TexObjPtr t1
= rmesa
->CurrentTexObj
[1];
944 if ( R128_DEBUG
& DEBUG_VERBOSE_MSG
) {
945 r128DDPrintDirty( "r128EmitHwStateLocked", rmesa
->dirty
);
948 if ( rmesa
->dirty
& (R128_UPLOAD_CONTEXT
|
952 R128_UPLOAD_CORE
) ) {
953 memcpy( &sarea
->context_state
, regs
, sizeof(sarea
->context_state
) );
956 if ( (rmesa
->dirty
& R128_UPLOAD_TEX0
) && t0
) {
957 drm_r128_texture_regs_t
*tex
= &sarea
->tex_state
[0];
959 tex
->tex_cntl
= t0
->setup
.tex_cntl
;
960 tex
->tex_combine_cntl
= rmesa
->tex_combine
[0];
961 tex
->tex_size_pitch
= t0
->setup
.tex_size_pitch
;
962 memcpy( &tex
->tex_offset
[0], &t0
->setup
.tex_offset
[0],
963 sizeof(tex
->tex_offset
) );
964 tex
->tex_border_color
= t0
->setup
.tex_border_color
;
967 if ( (rmesa
->dirty
& R128_UPLOAD_TEX1
) && t1
) {
968 drm_r128_texture_regs_t
*tex
= &sarea
->tex_state
[1];
970 tex
->tex_cntl
= t1
->setup
.tex_cntl
;
971 tex
->tex_combine_cntl
= rmesa
->tex_combine
[1];
972 tex
->tex_size_pitch
= t1
->setup
.tex_size_pitch
;
973 memcpy( &tex
->tex_offset
[0], &t1
->setup
.tex_offset
[0],
974 sizeof(tex
->tex_offset
) );
975 tex
->tex_border_color
= t1
->setup
.tex_border_color
;
978 sarea
->vertsize
= rmesa
->vertex_size
;
979 sarea
->vc_format
= rmesa
->vertex_format
;
981 /* Turn off the texture cache flushing */
982 rmesa
->setup
.tex_cntl_c
&= ~R128_TEX_CACHE_FLUSH
;
984 sarea
->dirty
|= rmesa
->dirty
;
985 rmesa
->dirty
&= R128_UPLOAD_CLIPRECTS
;
988 static void r128DDPrintState( const char *msg
, GLuint flags
)
991 "%s: (0x%x) %s%s%s%s%s%s%s%s\n",
994 (flags
& R128_NEW_CONTEXT
) ? "context, " : "",
995 (flags
& R128_NEW_ALPHA
) ? "alpha, " : "",
996 (flags
& R128_NEW_DEPTH
) ? "depth, " : "",
997 (flags
& R128_NEW_FOG
) ? "fog, " : "",
998 (flags
& R128_NEW_CLIP
) ? "clip, " : "",
999 (flags
& R128_NEW_CULL
) ? "cull, " : "",
1000 (flags
& R128_NEW_MASKS
) ? "masks, " : "",
1001 (flags
& R128_NEW_WINDOW
) ? "window, " : "" );
1004 void r128DDUpdateHWState( GLcontext
*ctx
)
1006 r128ContextPtr rmesa
= R128_CONTEXT(ctx
);
1007 int new_state
= rmesa
->new_state
;
1009 if ( new_state
|| rmesa
->NewGLState
& _NEW_TEXTURE
)
1011 FLUSH_BATCH( rmesa
);
1013 rmesa
->new_state
= 0;
1015 if ( R128_DEBUG
& DEBUG_VERBOSE_MSG
)
1016 r128DDPrintState( "r128UpdateHwState", new_state
);
1018 /* Update the various parts of the context's state.
1020 if ( new_state
& R128_NEW_ALPHA
)
1021 r128UpdateAlphaMode( ctx
);
1023 if ( new_state
& R128_NEW_DEPTH
)
1024 r128UpdateZMode( ctx
);
1026 if ( new_state
& R128_NEW_FOG
)
1027 r128UpdateFogAttrib( ctx
);
1029 if ( new_state
& R128_NEW_CLIP
)
1030 r128UpdateClipping( ctx
);
1032 if ( new_state
& R128_NEW_CULL
)
1033 r128UpdateCull( ctx
);
1035 if ( new_state
& R128_NEW_MASKS
)
1036 r128UpdateMasks( ctx
);
1038 if ( new_state
& R128_NEW_WINDOW
)
1039 r128UpdateWindow( ctx
);
1041 if ( rmesa
->NewGLState
& _NEW_TEXTURE
) {
1042 r128UpdateTextureState( ctx
);
1048 static void r128DDInvalidateState( GLcontext
*ctx
, GLuint new_state
)
1050 _swrast_InvalidateState( ctx
, new_state
);
1051 _swsetup_InvalidateState( ctx
, new_state
);
1052 _ac_InvalidateState( ctx
, new_state
);
1053 _tnl_InvalidateState( ctx
, new_state
);
1054 R128_CONTEXT(ctx
)->NewGLState
|= new_state
;
1059 /* Initialize the context's hardware state.
1061 void r128DDInitState( r128ContextPtr rmesa
)
1063 int dst_bpp
, depth_bpp
;
1065 switch ( rmesa
->r128Screen
->cpp
) {
1067 dst_bpp
= R128_GMC_DST_16BPP
;
1070 dst_bpp
= R128_GMC_DST_32BPP
;
1073 fprintf( stderr
, "Error: Unsupported pixel depth... exiting\n" );
1077 rmesa
->ClearColor
= 0x00000000;
1079 switch ( rmesa
->glCtx
->Visual
.depthBits
) {
1081 rmesa
->ClearDepth
= 0x0000ffff;
1082 depth_bpp
= R128_Z_PIX_WIDTH_16
;
1083 rmesa
->depth_scale
= 1.0 / (GLfloat
)0xffff;
1086 rmesa
->ClearDepth
= 0x00ffffff;
1087 depth_bpp
= R128_Z_PIX_WIDTH_24
;
1088 rmesa
->depth_scale
= 1.0 / (GLfloat
)0xffffff;
1091 fprintf( stderr
, "Error: Unsupported depth %d... exiting\n",
1092 rmesa
->glCtx
->Visual
.depthBits
);
1096 rmesa
->Fallback
= 0;
1100 rmesa
->setup
.dp_gui_master_cntl_c
= (R128_GMC_DST_PITCH_OFFSET_CNTL
|
1101 R128_GMC_DST_CLIPPING
|
1102 R128_GMC_BRUSH_SOLID_COLOR
|
1104 R128_GMC_SRC_DATATYPE_COLOR
|
1105 R128_GMC_BYTE_MSB_TO_LSB
|
1106 R128_GMC_CONVERSION_TEMP_6500
|
1108 R128_DP_SRC_SOURCE_MEMORY
|
1109 R128_GMC_3D_FCN_EN
|
1110 R128_GMC_CLR_CMP_CNTL_DIS
|
1111 R128_GMC_AUX_CLIP_DIS
|
1112 R128_GMC_WR_MSK_DIS
);
1114 rmesa
->setup
.sc_top_left_c
= 0x00000000;
1115 rmesa
->setup
.sc_bottom_right_c
= 0x1fff1fff;
1117 rmesa
->setup
.z_offset_c
= rmesa
->r128Screen
->depthOffset
;
1118 rmesa
->setup
.z_pitch_c
= ((rmesa
->r128Screen
->depthPitch
>> 3) |
1121 rmesa
->setup
.z_sten_cntl_c
= (depth_bpp
|
1123 R128_STENCIL_TEST_ALWAYS
|
1124 R128_STENCIL_S_FAIL_KEEP
|
1125 R128_STENCIL_ZPASS_KEEP
|
1126 R128_STENCIL_ZFAIL_KEEP
);
1128 rmesa
->setup
.tex_cntl_c
= (R128_Z_WRITE_ENABLE
|
1130 R128_DITHER_ENABLE
|
1131 R128_ALPHA_IN_TEX_COMPLETE_A
|
1133 R128_ALPHA_LIGHT_DIS
|
1134 R128_TEX_CACHE_FLUSH
|
1135 (0x3f << R128_LOD_BIAS_SHIFT
));
1137 rmesa
->setup
.misc_3d_state_cntl_reg
= (R128_MISC_SCALE_3D_TEXMAP_SHADE
|
1138 R128_MISC_SCALE_PIX_REPLICATE
|
1139 R128_ALPHA_COMB_ADD_CLAMP
|
1141 (R128_ALPHA_BLEND_ONE
<< R128_ALPHA_BLEND_SRC_SHIFT
) |
1142 (R128_ALPHA_BLEND_ZERO
<< R128_ALPHA_BLEND_DST_SHIFT
) |
1143 R128_ALPHA_TEST_ALWAYS
);
1145 rmesa
->setup
.texture_clr_cmp_clr_c
= 0x00000000;
1146 rmesa
->setup
.texture_clr_cmp_msk_c
= 0xffffffff;
1148 rmesa
->setup
.fog_color_c
= 0x00000000;
1150 rmesa
->setup
.pm4_vc_fpu_setup
= (R128_FRONT_DIR_CCW
|
1151 R128_BACKFACE_SOLID
|
1152 R128_FRONTFACE_SOLID
|
1153 R128_FPU_COLOR_GOURAUD
|
1154 R128_FPU_SUB_PIX_4BITS
|
1156 R128_TRAP_BITS_DISABLE
|
1159 R128_FLAT_SHADE_VERTEX_OGL
|
1160 R128_FPU_ROUND_TRUNCATE
|
1163 rmesa
->setup
.setup_cntl
= (R128_COLOR_GOURAUD
|
1164 R128_PRIM_TYPE_TRI
|
1165 R128_TEXTURE_ST_MULT_W
|
1166 R128_STARTING_VERTEX_1
|
1167 R128_ENDING_VERTEX_3
|
1168 R128_SU_POLY_LINE_NOT_LAST
|
1169 R128_SUB_PIX_4BITS
);
1171 rmesa
->setup
.tex_size_pitch_c
= 0x00000000;
1172 rmesa
->setup
.constant_color_c
= 0x00ffffff;
1174 rmesa
->setup
.dp_write_mask
= 0xffffffff;
1175 rmesa
->setup
.sten_ref_mask_c
= 0xffff0000;
1176 rmesa
->setup
.plane_3d_mask_c
= 0xffffffff;
1178 rmesa
->setup
.window_xy_offset
= 0x00000000;
1180 rmesa
->setup
.scale_3d_cntl
= (R128_SCALE_DITHER_TABLE
|
1181 R128_TEX_CACHE_SIZE_FULL
|
1182 R128_DITHER_INIT_RESET
|
1183 R128_SCALE_3D_TEXMAP_SHADE
|
1184 R128_SCALE_PIX_REPLICATE
|
1185 R128_ALPHA_COMB_ADD_CLAMP
|
1187 (R128_ALPHA_BLEND_ONE
<< R128_ALPHA_BLEND_SRC_SHIFT
) |
1188 (R128_ALPHA_BLEND_ZERO
<< R128_ALPHA_BLEND_DST_SHIFT
) |
1189 R128_ALPHA_TEST_ALWAYS
|
1190 R128_COMPOSITE_SHADOW_CMP_EQUAL
|
1191 R128_TEX_MAP_ALPHA_IN_TEXTURE
|
1192 R128_TEX_CACHE_LINE_SIZE_4QW
);
1194 rmesa
->new_state
= R128_NEW_ALL
;
1197 /* Initialize the driver's state functions.
1199 void r128DDInitStateFuncs( GLcontext
*ctx
)
1201 ctx
->Driver
.UpdateState
= r128DDInvalidateState
;
1203 ctx
->Driver
.ClearIndex
= NULL
;
1204 ctx
->Driver
.ClearColor
= r128DDClearColor
;
1205 ctx
->Driver
.DrawBuffer
= r128DDDrawBuffer
;
1206 ctx
->Driver
.ReadBuffer
= r128DDReadBuffer
;
1208 ctx
->Driver
.IndexMask
= NULL
;
1209 ctx
->Driver
.ColorMask
= r128DDColorMask
;
1210 ctx
->Driver
.AlphaFunc
= r128DDAlphaFunc
;
1211 ctx
->Driver
.BlendEquationSeparate
= r128DDBlendEquationSeparate
;
1212 ctx
->Driver
.BlendFuncSeparate
= r128DDBlendFuncSeparate
;
1213 ctx
->Driver
.ClearDepth
= r128DDClearDepth
;
1214 ctx
->Driver
.CullFace
= r128DDCullFace
;
1215 ctx
->Driver
.FrontFace
= r128DDFrontFace
;
1216 ctx
->Driver
.DepthFunc
= r128DDDepthFunc
;
1217 ctx
->Driver
.DepthMask
= r128DDDepthMask
;
1218 ctx
->Driver
.Enable
= r128DDEnable
;
1219 ctx
->Driver
.Fogfv
= r128DDFogfv
;
1220 ctx
->Driver
.Hint
= NULL
;
1221 ctx
->Driver
.Lightfv
= NULL
;
1222 ctx
->Driver
.LightModelfv
= r128DDLightModelfv
;
1223 ctx
->Driver
.LogicOpcode
= r128DDLogicOpCode
;
1224 ctx
->Driver
.PolygonMode
= NULL
;
1225 ctx
->Driver
.PolygonStipple
= r128DDPolygonStipple
;
1226 ctx
->Driver
.RenderMode
= r128DDRenderMode
;
1227 ctx
->Driver
.Scissor
= r128DDScissor
;
1228 ctx
->Driver
.ShadeModel
= r128DDShadeModel
;
1230 ctx
->Driver
.DepthRange
= r128DepthRange
;
1231 ctx
->Driver
.Viewport
= r128Viewport
;
1233 /* Pixel path fallbacks.
1235 ctx
->Driver
.Accum
= _swrast_Accum
;
1236 ctx
->Driver
.Bitmap
= _swrast_Bitmap
;
1237 ctx
->Driver
.CopyPixels
= _swrast_CopyPixels
;
1238 ctx
->Driver
.DrawPixels
= _swrast_DrawPixels
;
1239 ctx
->Driver
.ReadPixels
= _swrast_ReadPixels
;
1241 /* Swrast hooks for imaging extensions:
1243 ctx
->Driver
.CopyColorTable
= _swrast_CopyColorTable
;
1244 ctx
->Driver
.CopyColorSubTable
= _swrast_CopyColorSubTable
;
1245 ctx
->Driver
.CopyConvolutionFilter1D
= _swrast_CopyConvolutionFilter1D
;
1246 ctx
->Driver
.CopyConvolutionFilter2D
= _swrast_CopyConvolutionFilter2D
;