2 * GLX Hardware Device Driver for Intel i810
3 * Copyright (C) 1999 Keith Whitwell
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 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included
13 * in all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * KEITH WHITWELL, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM,
19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
21 * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 #include "main/glheader.h"
26 #include "main/macros.h"
27 #include "main/mtypes.h"
28 #include "main/texformat.h"
29 #include "main/simple_list.h"
30 #include "main/enums.h"
33 #include "i810screen.h"
36 #include "i810context.h"
38 #include "i810state.h"
39 #include "i810ioctl.h"
44 static void i810SetTexImages( i810ContextPtr imesa
,
45 struct gl_texture_object
*tObj
)
47 GLuint height
, width
, pitch
, i
, textureFormat
, log_pitch
;
48 i810TextureObjectPtr t
= (i810TextureObjectPtr
) tObj
->DriverData
;
49 const struct gl_texture_image
*baseImage
= tObj
->Image
[0][tObj
->BaseLevel
];
51 GLint log2Width
, log2Height
;
53 /* fprintf(stderr, "%s\n", __FUNCTION__); */
56 switch (baseImage
->TexFormat
->MesaFormat
) {
57 case MESA_FORMAT_ARGB1555
:
58 textureFormat
= MI1_FMT_16BPP
| MI1_PF_16BPP_ARGB1555
;
60 case MESA_FORMAT_ARGB4444
:
61 textureFormat
= MI1_FMT_16BPP
| MI1_PF_16BPP_ARGB4444
;
63 case MESA_FORMAT_RGB565
:
64 textureFormat
= MI1_FMT_16BPP
| MI1_PF_16BPP_RGB565
;
66 case MESA_FORMAT_AL88
:
67 textureFormat
= MI1_FMT_16BPP
| MI1_PF_16BPP_AY88
;
69 case MESA_FORMAT_YCBCR
:
70 textureFormat
= MI1_FMT_422
| MI1_PF_422_YCRCB_SWAP_Y
71 | MI1_COLOR_CONV_ENABLE
;
73 case MESA_FORMAT_YCBCR_REV
:
74 textureFormat
= MI1_FMT_422
| MI1_PF_422_YCRCB
75 | MI1_COLOR_CONV_ENABLE
;
78 textureFormat
= MI1_FMT_8CI
| MI1_PF_8CI_ARGB4444
;
83 fprintf(stderr
, "i810SetTexImages: bad image->Format\n" );
87 driCalculateTextureFirstLastLevel( (driTextureObject
*) t
);
89 numLevels
= t
->base
.lastLevel
- t
->base
.firstLevel
+ 1;
91 log2Width
= tObj
->Image
[0][t
->base
.firstLevel
]->WidthLog2
;
92 log2Height
= tObj
->Image
[0][t
->base
.firstLevel
]->HeightLog2
;
94 /* Figure out the amount of memory required to hold all the mipmap
95 * levels. Choose the smallest pitch to accomodate the largest
98 width
= tObj
->Image
[0][t
->base
.firstLevel
]->Width
* t
->texelBytes
;
99 for (pitch
= 32, log_pitch
=2 ; pitch
< width
; pitch
*= 2 )
102 /* All images must be loaded at this pitch. Count the number of
105 for ( height
= i
= 0 ; i
< numLevels
; i
++ ) {
106 t
->image
[i
].image
= tObj
->Image
[0][t
->base
.firstLevel
+ i
];
107 t
->image
[i
].offset
= height
* pitch
;
108 t
->image
[i
].internalFormat
= baseImage
->_BaseFormat
;
109 height
+= t
->image
[i
].image
->Height
;
113 t
->base
.totalSize
= height
*pitch
;
115 t
->dirty
= I810_UPLOAD_TEX0
| I810_UPLOAD_TEX1
;
116 t
->Setup
[I810_TEXREG_MI1
] = (MI1_MAP_0
| textureFormat
| log_pitch
);
117 t
->Setup
[I810_TEXREG_MLL
] = (GFX_OP_MAP_LOD_LIMITS
|
121 ((numLevels
- 1) << MLL_MIN_MIP_SHIFT
));
123 LOCK_HARDWARE( imesa
);
124 i810UploadTexImagesLocked( imesa
, t
);
125 UNLOCK_HARDWARE( imesa
);
128 /* ================================================================
129 * Texture combine functions
133 static void set_color_stage( unsigned color
, int stage
,
134 i810ContextPtr imesa
)
136 if ( color
!= imesa
->Setup
[I810_CTXREG_MC0
+ stage
] ) {
137 I810_STATECHANGE( imesa
, I810_UPLOAD_CTX
);
138 imesa
->Setup
[I810_CTXREG_MC0
+ stage
] = color
;
143 static void set_alpha_stage( unsigned alpha
, int stage
,
144 i810ContextPtr imesa
)
146 if ( alpha
!= imesa
->Setup
[I810_CTXREG_MA0
+ stage
] ) {
147 I810_STATECHANGE( imesa
, I810_UPLOAD_CTX
);
148 imesa
->Setup
[I810_CTXREG_MA0
+ stage
] = alpha
;
153 static const unsigned operand_modifiers
[] = {
155 MC_ARG_REPLICATE_ALPHA
, MC_ARG_INVERT
| MC_ARG_REPLICATE_ALPHA
159 * Configure the hardware bits for the specified texture environment.
161 * Configures the hardware bits for the texture environment state for the
162 * specified texture unit. As combine stages are added, the values pointed
163 * to by \c color_stage and \c alpha_stage are incremented.
165 * \param ctx GL context pointer.
166 * \param unit Texture unit to be added.
167 * \param color_stage Next available hardware color combine stage.
168 * \param alpha_stage Next available hardware alpha combine stage.
171 * If the combine mode for the specified texture unit could be added without
172 * requiring a software fallback, \c GL_TRUE is returned. Otherwise,
173 * \c GL_FALSE is returned.
176 * If the mode is (GL_REPLACE, GL_PREVIOUS), treat it as though the texture
177 * stage is disabled. That is, don't emit any combine stages.
180 * Add support for ATI_texture_env_combine3 modes. This will require using
181 * two combine stages.
184 * Add support for the missing \c GL_INTERPOLATE modes. This will require
185 * using all three combine stages. There is a comment in the function
186 * describing how this might work.
189 * If, after all the combine stages have been emitted, a texture is never
190 * actually used, disable the texture unit. That should save texture some
191 * memory bandwidth. This won't happen in this function, but this seems like
192 * a reasonable place to make note of it.
195 i810UpdateTexEnvCombine( GLcontext
*ctx
, GLuint unit
,
196 int * color_stage
, int * alpha_stage
)
198 i810ContextPtr imesa
= I810_CONTEXT(ctx
);
199 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
200 GLuint color_arg
[3] = {
201 MC_ARG_ONE
, MC_ARG_ONE
, MC_ARG_ONE
203 GLuint alpha_arg
[3] = {
204 MA_ARG_ITERATED_ALPHA
, MA_ARG_ITERATED_ALPHA
, MA_ARG_ITERATED_ALPHA
207 GLuint color_combine
, alpha_combine
;
208 const GLuint numColorArgs
= texUnit
->_CurrentCombine
->_NumArgsRGB
;
209 const GLuint numAlphaArgs
= texUnit
->_CurrentCombine
->_NumArgsA
;
210 GLuint RGBshift
= texUnit
->_CurrentCombine
->ScaleShiftRGB
;
211 GLuint Ashift
= texUnit
->_CurrentCombine
->ScaleShiftA
;
214 if ( !texUnit
->_ReallyEnabled
) {
219 if ((*color_stage
>= 3) || (*alpha_stage
>= 3)) {
225 * Extract the color and alpha combine function arguments.
228 for ( i
= 0 ; i
< numColorArgs
; i
++ ) {
229 unsigned op
= texUnit
->_CurrentCombine
->OperandRGB
[i
] - GL_SRC_COLOR
;
232 switch ( texUnit
->_CurrentCombine
->SourceRGB
[i
] ) {
234 color_arg
[i
] = MC_ARG_TEX0_COLOR
;
237 color_arg
[i
] = MC_ARG_TEX1_COLOR
;
240 color_arg
[i
] = (unit
== 0)
241 ? MC_ARG_TEX0_COLOR
: MC_ARG_TEX1_COLOR
;
244 color_arg
[i
] = MC_ARG_COLOR_FACTOR
;
246 case GL_PRIMARY_COLOR
:
247 color_arg
[i
] = MC_ARG_ITERATED_COLOR
;
250 color_arg
[i
] = (unit
== 0)
251 ? MC_ARG_ITERATED_COLOR
: MC_ARG_CURRENT_COLOR
;
254 /* Toggle the low bit of the op value. The is the 'invert' bit,
255 * and it acts to convert GL_ZERO+op to the equivalent GL_ONE+op.
262 color_arg
[i
] = MC_ARG_ONE
;
268 color_arg
[i
] |= operand_modifiers
[op
];
272 for ( i
= 0 ; i
< numAlphaArgs
; i
++ ) {
273 unsigned op
= texUnit
->_CurrentCombine
->OperandA
[i
] - GL_SRC_ALPHA
;
276 switch ( texUnit
->_CurrentCombine
->SourceA
[i
] ) {
278 alpha_arg
[i
] = MA_ARG_TEX0_ALPHA
;
281 alpha_arg
[i
] = MA_ARG_TEX1_ALPHA
;
284 alpha_arg
[i
] = (unit
== 0)
285 ? MA_ARG_TEX0_ALPHA
: MA_ARG_TEX1_ALPHA
;
288 alpha_arg
[i
] = MA_ARG_ALPHA_FACTOR
;
290 case GL_PRIMARY_COLOR
:
291 alpha_arg
[i
] = MA_ARG_ITERATED_ALPHA
;
294 alpha_arg
[i
] = (unit
== 0)
295 ? MA_ARG_ITERATED_ALPHA
: MA_ARG_CURRENT_ALPHA
;
298 /* Toggle the low bit of the op value. The is the 'invert' bit,
299 * and it acts to convert GL_ZERO+op to the equivalent GL_ONE+op.
310 alpha_arg
[i
] = MA_ARG_ONE
;
316 alpha_arg
[i
] |= operand_modifiers
[op
];
321 * Build up the color and alpha combine functions.
323 switch ( texUnit
->_CurrentCombine
->ModeRGB
) {
325 color_combine
= MC_OP_ARG1
;
328 color_combine
= MC_OP_MODULATE
+ RGBshift
;
332 color_combine
= MC_OP_ADD
;
335 color_combine
= MC_OP_ADD_SIGNED
;
338 color_combine
= MC_OP_SUBTRACT
;
341 /* For interpolation, the i810 hardware has some limitations. It
342 * can't handle using the secondary or diffuse color (diffuse alpha
343 * is okay) for the third argument.
345 * It is possible to emulate the missing modes by using multiple
346 * combine stages. Unfortunately it requires all three stages to
347 * emulate a single interpolate stage. The (arg0*arg2) portion is
348 * done in stage zero and writes to MC_DEST_ACCUMULATOR. The
349 * (arg1*(1-arg2)) portion is done in stage 1, and the final stage is
350 * (MC_ARG1_ACCUMULATOR | MC_ARG2_CURRENT_COLOR | MC_OP_ADD).
352 * It can also be done without using the accumulator by rearranging
353 * the equation as (arg1 + (arg2 * (arg0 - arg1))). Too bad the i810
354 * doesn't support the MODULATE_AND_ADD mode that the i830 supports.
355 * If it did, the interpolate could be done in only two stages.
358 if ( (color_arg
[2] & MC_ARG_INVERT
) != 0 ) {
359 unsigned temp
= color_arg
[0];
361 color_arg
[0] = color_arg
[1];
363 color_arg
[2] &= ~MC_ARG_INVERT
;
366 switch (color_arg
[2]) {
368 case (MC_ARG_ONE
| MC_ARG_REPLICATE_ALPHA
):
369 color_combine
= MC_OP_ARG1
;
370 color_arg
[1] = MC_ARG_ONE
;
373 case (MC_ARG_COLOR_FACTOR
):
376 case (MC_ARG_COLOR_FACTOR
| MC_ARG_REPLICATE_ALPHA
):
377 color_combine
= MC_OP_LIN_BLEND_ALPHA_FACTOR
;
380 case (MC_ARG_ITERATED_COLOR
):
383 case (MC_ARG_ITERATED_COLOR
| MC_ARG_REPLICATE_ALPHA
):
384 color_combine
= MC_OP_LIN_BLEND_ITER_ALPHA
;
387 case (MC_ARG_SPECULAR_COLOR
):
388 case (MC_ARG_SPECULAR_COLOR
| MC_ARG_REPLICATE_ALPHA
):
391 case (MC_ARG_TEX0_COLOR
):
392 color_combine
= MC_OP_LIN_BLEND_TEX0_COLOR
;
395 case (MC_ARG_TEX0_COLOR
| MC_ARG_REPLICATE_ALPHA
):
396 color_combine
= MC_OP_LIN_BLEND_TEX0_ALPHA
;
399 case (MC_ARG_TEX1_COLOR
):
400 color_combine
= MC_OP_LIN_BLEND_TEX1_COLOR
;
403 case (MC_ARG_TEX1_COLOR
| MC_ARG_REPLICATE_ALPHA
):
404 color_combine
= MC_OP_LIN_BLEND_TEX1_ALPHA
;
417 switch ( texUnit
->_CurrentCombine
->ModeA
) {
419 alpha_combine
= MA_OP_ARG1
;
422 alpha_combine
= MA_OP_MODULATE
+ Ashift
;
426 alpha_combine
= MA_OP_ADD
;
429 alpha_combine
= MA_OP_ADD_SIGNED
;
432 alpha_combine
= MA_OP_SUBTRACT
;
435 if ( (alpha_arg
[2] & MA_ARG_INVERT
) != 0 ) {
436 unsigned temp
= alpha_arg
[0];
438 alpha_arg
[0] = alpha_arg
[1];
440 alpha_arg
[2] &= ~MA_ARG_INVERT
;
443 switch (alpha_arg
[2]) {
445 alpha_combine
= MA_OP_ARG1
;
446 alpha_arg
[1] = MA_ARG_ITERATED_ALPHA
;
449 case MA_ARG_ALPHA_FACTOR
:
450 alpha_combine
= MA_OP_LIN_BLEND_ALPHA_FACTOR
;
453 case MA_ARG_ITERATED_ALPHA
:
454 alpha_combine
= MA_OP_LIN_BLEND_ITER_ALPHA
;
457 case MA_ARG_TEX0_ALPHA
:
458 alpha_combine
= MA_OP_LIN_BLEND_TEX0_ALPHA
;
461 case MA_ARG_TEX1_ALPHA
:
462 alpha_combine
= MA_OP_LIN_BLEND_TEX1_ALPHA
;
475 color_combine
|= GFX_OP_MAP_COLOR_STAGES
| (*color_stage
<< MC_STAGE_SHIFT
)
476 | MC_UPDATE_DEST
| MC_DEST_CURRENT
477 | MC_UPDATE_ARG1
| (color_arg
[0] << MC_ARG1_SHIFT
)
478 | MC_UPDATE_ARG2
| (color_arg
[1] << MC_ARG2_SHIFT
)
481 alpha_combine
|= GFX_OP_MAP_ALPHA_STAGES
| (*alpha_stage
<< MA_STAGE_SHIFT
)
482 | MA_UPDATE_ARG1
| (alpha_arg
[0] << MA_ARG1_SHIFT
)
483 | MA_UPDATE_ARG2
| (alpha_arg
[1] << MA_ARG2_SHIFT
)
486 set_color_stage( color_combine
, *color_stage
, imesa
);
487 set_alpha_stage( alpha_combine
, *alpha_stage
, imesa
);
493 * Apply the scale factor.
495 /* The only operation where the i810 directly supports adding a post-
496 * scale factor is modulate. For all the other modes the post-scale is
497 * emulated by inserting and extra modulate stage. For the modulate
498 * case, the scaling is handled above when color_combine / alpha_combine
502 if ( RGBshift
!= 0 ) {
503 const unsigned color_scale
= GFX_OP_MAP_COLOR_STAGES
504 | (*color_stage
<< MC_STAGE_SHIFT
)
505 | MC_UPDATE_DEST
| MC_DEST_CURRENT
506 | MC_UPDATE_ARG1
| (MC_ARG_CURRENT_COLOR
<< MC_ARG1_SHIFT
)
507 | MC_UPDATE_ARG2
| (MC_ARG_ONE
<< MC_ARG2_SHIFT
)
508 | MC_UPDATE_OP
| (MC_OP_MODULATE
+ RGBshift
);
510 if ( *color_stage
>= 3 ) {
514 set_color_stage( color_scale
, *color_stage
, imesa
);
520 const unsigned alpha_scale
= GFX_OP_MAP_ALPHA_STAGES
521 | (*alpha_stage
<< MA_STAGE_SHIFT
)
522 | MA_UPDATE_ARG1
| (MA_ARG_CURRENT_ALPHA
<< MA_ARG1_SHIFT
)
523 | MA_UPDATE_ARG2
| (MA_ARG_ONE
<< MA_ARG2_SHIFT
)
524 | MA_UPDATE_OP
| (MA_OP_MODULATE
+ Ashift
);
526 if ( *alpha_stage
>= 3 ) {
530 set_alpha_stage( alpha_scale
, *alpha_stage
, imesa
);
537 static GLboolean
enable_tex_common( GLcontext
*ctx
, GLuint unit
)
539 i810ContextPtr imesa
= I810_CONTEXT(ctx
);
540 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
541 struct gl_texture_object
*tObj
= texUnit
->_Current
;
542 i810TextureObjectPtr t
= (i810TextureObjectPtr
)tObj
->DriverData
;
544 if (tObj
->Image
[0][tObj
->BaseLevel
]->Border
> 0) {
548 /* Upload teximages (not pipelined)
550 if (t
->base
.dirty_images
[0]) {
551 I810_FIREVERTICES(imesa
);
552 i810SetTexImages( imesa
, tObj
);
553 if (!t
->base
.memBlock
) {
558 /* Update state if this is a different texture object to last
561 if (imesa
->CurrentTexObj
[unit
] != t
) {
562 I810_STATECHANGE(imesa
, (I810_UPLOAD_TEX0
<<unit
));
563 imesa
->CurrentTexObj
[unit
] = t
;
564 t
->base
.bound
|= (1U << unit
);
566 /* XXX: should be locked */
567 driUpdateTextureLRU( (driTextureObject
*) t
);
570 imesa
->TexEnvImageFmt
[unit
] = tObj
->Image
[0][tObj
->BaseLevel
]->_BaseFormat
;
574 static GLboolean
enable_tex_rect( GLcontext
*ctx
, GLuint unit
)
576 i810ContextPtr imesa
= I810_CONTEXT(ctx
);
577 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
578 struct gl_texture_object
*tObj
= texUnit
->_Current
;
579 i810TextureObjectPtr t
= (i810TextureObjectPtr
)tObj
->DriverData
;
582 Width
= tObj
->Image
[0][t
->base
.firstLevel
]->Width
- 1;
583 Height
= tObj
->Image
[0][t
->base
.firstLevel
]->Height
- 1;
585 I810_STATECHANGE(imesa
, (I810_UPLOAD_TEX0
<<unit
));
586 t
->Setup
[I810_TEXREG_MCS
] &= ~MCS_NORMALIZED_COORDS
;
587 t
->Setup
[I810_TEXREG_MCS
] |= MCS_UPDATE_NORMALIZED
;
588 t
->Setup
[I810_TEXREG_MI2
] = (MI2_DIMENSIONS_ARE_EXACT
|
589 (Height
<< MI2_HEIGHT_SHIFT
) | Width
);
594 static GLboolean
enable_tex_2d( GLcontext
*ctx
, GLuint unit
)
596 i810ContextPtr imesa
= I810_CONTEXT(ctx
);
597 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
598 struct gl_texture_object
*tObj
= texUnit
->_Current
;
599 i810TextureObjectPtr t
= (i810TextureObjectPtr
)tObj
->DriverData
;
600 GLint log2Width
, log2Height
;
603 log2Width
= tObj
->Image
[0][t
->base
.firstLevel
]->WidthLog2
;
604 log2Height
= tObj
->Image
[0][t
->base
.firstLevel
]->HeightLog2
;
606 I810_STATECHANGE(imesa
, (I810_UPLOAD_TEX0
<<unit
));
607 t
->Setup
[I810_TEXREG_MCS
] |= MCS_NORMALIZED_COORDS
| MCS_UPDATE_NORMALIZED
;
608 t
->Setup
[I810_TEXREG_MI2
] = (MI2_DIMENSIONS_ARE_LOG2
|
609 (log2Height
<< MI2_HEIGHT_SHIFT
) | log2Width
);
614 static void disable_tex( GLcontext
*ctx
, GLuint unit
)
616 i810ContextPtr imesa
= I810_CONTEXT(ctx
);
618 imesa
->CurrentTexObj
[unit
] = 0;
619 imesa
->TexEnvImageFmt
[unit
] = 0;
620 imesa
->dirty
&= ~(I810_UPLOAD_TEX0
<<unit
);
625 * Update hardware state for a texture unit.
628 * 1D textures should be supported! Just use a 2D texture with the second
629 * texture coordinate value fixed at 0.0.
631 static void i810UpdateTexUnit( GLcontext
*ctx
, GLuint unit
,
632 int * next_color_stage
, int * next_alpha_stage
)
634 i810ContextPtr imesa
= I810_CONTEXT(ctx
);
635 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
638 switch(texUnit
->_ReallyEnabled
) {
640 ret
= enable_tex_common( ctx
, unit
);
641 ret
&= enable_tex_2d(ctx
, unit
);
642 if (ret
== GL_FALSE
) {
643 FALLBACK( imesa
, I810_FALLBACK_TEXTURE
, GL_TRUE
);
646 case TEXTURE_RECT_BIT
:
647 ret
= enable_tex_common( ctx
, unit
);
648 ret
&= enable_tex_rect(ctx
, unit
);
649 if (ret
== GL_FALSE
) {
650 FALLBACK( imesa
, I810_FALLBACK_TEXTURE
, GL_TRUE
);
654 disable_tex(ctx
, unit
);
659 if (!i810UpdateTexEnvCombine( ctx
, unit
,
660 next_color_stage
, next_alpha_stage
)) {
661 FALLBACK( imesa
, I810_FALLBACK_TEXTURE
, GL_TRUE
);
668 void i810UpdateTextureState( GLcontext
*ctx
)
670 static const unsigned color_pass
[3] = {
671 GFX_OP_MAP_COLOR_STAGES
| MC_STAGE_0
| MC_UPDATE_DEST
| MC_DEST_CURRENT
672 | MC_UPDATE_ARG1
| (MC_ARG_ITERATED_COLOR
<< MC_ARG1_SHIFT
)
673 | MC_UPDATE_ARG2
| (MC_ARG_ONE
<< MC_ARG2_SHIFT
)
674 | MC_UPDATE_OP
| MC_OP_ARG1
,
675 GFX_OP_MAP_COLOR_STAGES
| MC_STAGE_1
| MC_UPDATE_DEST
| MC_DEST_CURRENT
676 | MC_UPDATE_ARG1
| (MC_ARG_CURRENT_COLOR
<< MC_ARG1_SHIFT
)
677 | MC_UPDATE_ARG2
| (MC_ARG_ONE
<< MC_ARG2_SHIFT
)
678 | MC_UPDATE_OP
| MC_OP_ARG1
,
679 GFX_OP_MAP_COLOR_STAGES
| MC_STAGE_2
| MC_UPDATE_DEST
| MC_DEST_CURRENT
680 | MC_UPDATE_ARG1
| (MC_ARG_CURRENT_COLOR
<< MC_ARG1_SHIFT
)
681 | MC_UPDATE_ARG2
| (MC_ARG_ONE
<< MC_ARG2_SHIFT
)
682 | MC_UPDATE_OP
| MC_OP_ARG1
684 static const unsigned alpha_pass
[3] = {
685 GFX_OP_MAP_ALPHA_STAGES
| MA_STAGE_0
686 | MA_UPDATE_ARG1
| (MA_ARG_ITERATED_ALPHA
<< MA_ARG1_SHIFT
)
687 | MA_UPDATE_ARG2
| (MA_ARG_ITERATED_ALPHA
<< MA_ARG2_SHIFT
)
688 | MA_UPDATE_OP
| MA_OP_ARG1
,
689 GFX_OP_MAP_ALPHA_STAGES
| MA_STAGE_1
690 | MA_UPDATE_ARG1
| (MA_ARG_CURRENT_ALPHA
<< MA_ARG1_SHIFT
)
691 | MA_UPDATE_ARG2
| (MA_ARG_CURRENT_ALPHA
<< MA_ARG2_SHIFT
)
692 | MA_UPDATE_OP
| MA_OP_ARG1
,
693 GFX_OP_MAP_ALPHA_STAGES
| MA_STAGE_2
694 | MA_UPDATE_ARG1
| (MA_ARG_CURRENT_ALPHA
<< MA_ARG1_SHIFT
)
695 | MA_UPDATE_ARG2
| (MA_ARG_CURRENT_ALPHA
<< MA_ARG2_SHIFT
)
696 | MA_UPDATE_OP
| MA_OP_ARG1
698 i810ContextPtr imesa
= I810_CONTEXT(ctx
);
699 int next_color_stage
= 0;
700 int next_alpha_stage
= 0;
703 /* fprintf(stderr, "%s\n", __FUNCTION__); */
704 FALLBACK( imesa
, I810_FALLBACK_TEXTURE
, GL_FALSE
);
706 i810UpdateTexUnit( ctx
, 0, & next_color_stage
, & next_alpha_stage
);
707 i810UpdateTexUnit( ctx
, 1, & next_color_stage
, & next_alpha_stage
);
709 /* There needs to be at least one combine stage emitted that just moves
710 * the incoming primary color to the current color register. In addition,
711 * there number be the same number of color and alpha stages emitted.
712 * Finally, if there are less than 3 combine stages, a MC_OP_DISABLE stage
716 while ( (next_color_stage
== 0) ||
717 (next_color_stage
< next_alpha_stage
) ) {
718 set_color_stage( color_pass
[ next_color_stage
], next_color_stage
,
723 assert( next_color_stage
<= 3 );
725 while ( next_alpha_stage
< next_color_stage
) {
726 set_alpha_stage( alpha_pass
[ next_alpha_stage
], next_alpha_stage
,
731 assert( next_alpha_stage
<= 3 );
732 assert( next_color_stage
== next_alpha_stage
);
734 if ( next_color_stage
< 3 ) {
735 const unsigned color
= GFX_OP_MAP_COLOR_STAGES
736 | (next_color_stage
<< MC_STAGE_SHIFT
)
737 | MC_UPDATE_DEST
| MC_DEST_CURRENT
738 | MC_UPDATE_ARG1
| (MC_ARG_ONE
<< MC_ARG1_SHIFT
)
739 | MC_UPDATE_ARG2
| (MC_ARG_ONE
<< MC_ARG2_SHIFT
)
740 | MC_UPDATE_OP
| (MC_OP_DISABLE
);
742 const unsigned alpha
= GFX_OP_MAP_ALPHA_STAGES
743 | (next_color_stage
<< MC_STAGE_SHIFT
)
744 | MA_UPDATE_ARG1
| (MA_ARG_CURRENT_ALPHA
<< MA_ARG1_SHIFT
)
745 | MA_UPDATE_ARG2
| (MA_ARG_CURRENT_ALPHA
<< MA_ARG2_SHIFT
)
746 | MA_UPDATE_OP
| (MA_OP_ARG1
);
748 set_color_stage( color
, next_color_stage
, imesa
);
749 set_alpha_stage( alpha
, next_alpha_stage
, imesa
);