1 /**************************************************************************
3 * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 **************************************************************************/
31 #include "simple_list.h"
33 #include "texformat.h"
38 #include "intel_screen.h"
39 #include "intel_ioctl.h"
40 #include "intel_tex.h"
42 #include "i830_context.h"
46 /* ================================================================
47 * Texture combine functions
49 static GLuint
pass_through( GLuint
*state
, GLuint blendUnit
)
51 state
[0] = (_3DSTATE_MAP_BLEND_OP_CMD(blendUnit
) |
53 ENABLE_TEXOUTPUT_WRT_SEL
|
54 TEXOP_OUTPUT_CURRENT
|
55 DISABLE_TEX_CNTRL_STAGE
|
59 state
[1] = (_3DSTATE_MAP_BLEND_OP_CMD(blendUnit
) |
61 ENABLE_TEXOUTPUT_WRT_SEL
|
62 TEXOP_OUTPUT_CURRENT
|
66 state
[2] = (_3DSTATE_MAP_BLEND_ARG_CMD(blendUnit
) |
69 TEXBLENDARG_MODIFY_PARMS
|
71 state
[3] = (_3DSTATE_MAP_BLEND_ARG_CMD(blendUnit
) |
74 TEXBLENDARG_MODIFY_PARMS
|
80 static GLuint
emit_factor( GLuint blendUnit
, GLuint
*state
, GLuint count
,
81 const GLfloat
*factor
)
87 fprintf(stderr
, "emit constant %d: %.2f %.2f %.2f %.2f\n",
88 blendUnit
, factor
[0], factor
[1], factor
[2], factor
[3]);
90 UNCLAMPED_FLOAT_TO_UBYTE(r
, factor
[0]);
91 UNCLAMPED_FLOAT_TO_UBYTE(g
, factor
[1]);
92 UNCLAMPED_FLOAT_TO_UBYTE(b
, factor
[2]);
93 UNCLAMPED_FLOAT_TO_UBYTE(a
, factor
[3]);
95 col
= ((a
<< 24) | (r
<< 16) | (g
<< 8) | b
);
97 state
[count
++] = _3DSTATE_COLOR_FACTOR_N_CMD(blendUnit
);
104 static __inline__ GLuint
GetTexelOp(GLint unit
)
107 case 0: return TEXBLENDARG_TEXEL0
;
108 case 1: return TEXBLENDARG_TEXEL1
;
109 case 2: return TEXBLENDARG_TEXEL2
;
110 case 3: return TEXBLENDARG_TEXEL3
;
111 default: return TEXBLENDARG_TEXEL0
;
117 * Calculate the hardware instuctions to setup the current texture enviromnemt
118 * settings. Since \c gl_texture_unit::_CurrentCombine is used, both
119 * "classic" texture enviroments and GL_ARB_texture_env_combine type texture
120 * environments are treated identically.
123 * This function should return \c GLboolean. When \c GL_FALSE is returned,
124 * it means that an environment is selected that the hardware cannot do. This
125 * is the way the Radeon and R200 drivers work.
128 * Looking at i830_3d_regs.h, it seems the i830 can do part of
129 * GL_ATI_texture_env_combine3. It can handle using \c GL_ONE and
130 * \c GL_ZERO as combine inputs (which the code already supports). It can
131 * also handle the \c GL_MODULATE_ADD_ATI mode. Is it worth investigating
132 * partial support for the extension?
135 i830SetTexEnvCombine(i830ContextPtr i830
,
136 const struct gl_tex_env_combine_state
* combine
,
140 const GLfloat
*factor
)
142 const GLuint numColorArgs
= combine
->_NumArgsRGB
;
143 const GLuint numAlphaArgs
= combine
->_NumArgsA
;
151 GLboolean need_factor
= 0;
154 static const GLuint tex_blend_rgb
[3] = {
155 TEXPIPE_COLOR
| TEXBLEND_ARG1
| TEXBLENDARG_MODIFY_PARMS
,
156 TEXPIPE_COLOR
| TEXBLEND_ARG2
| TEXBLENDARG_MODIFY_PARMS
,
157 TEXPIPE_COLOR
| TEXBLEND_ARG0
| TEXBLENDARG_MODIFY_PARMS
,
159 static const GLuint tex_blend_a
[3] = {
160 TEXPIPE_ALPHA
| TEXBLEND_ARG1
| TEXBLENDARG_MODIFY_PARMS
,
161 TEXPIPE_ALPHA
| TEXBLEND_ARG2
| TEXBLENDARG_MODIFY_PARMS
,
162 TEXPIPE_ALPHA
| TEXBLEND_ARG0
| TEXBLENDARG_MODIFY_PARMS
,
164 static const GLuint op_rgb
[4] = {
167 TEXBLENDARG_REPLICATE_ALPHA
,
168 TEXBLENDARG_REPLICATE_ALPHA
| TEXBLENDARG_INV_ARG
,
171 if(INTEL_DEBUG
&DEBUG_TEXTURE
)
172 fprintf(stderr
, "%s\n", __FUNCTION__
);
175 /* The EXT version of the DOT3 extension does not support the
176 * scale factor, but the ARB version (and the version in OpenGL
179 switch (combine
->ModeRGB
) {
180 case GL_DOT3_RGB_EXT
:
181 alpha_shift
= combine
->ScaleShiftA
;
185 case GL_DOT3_RGBA_EXT
:
191 rgb_shift
= combine
->ScaleShiftRGB
;
192 alpha_shift
= combine
->ScaleShiftA
;
197 switch(combine
->ModeRGB
) {
199 blendop
= TEXBLENDOP_ARG1
;
202 blendop
= TEXBLENDOP_MODULATE
;
205 blendop
= TEXBLENDOP_ADD
;
208 blendop
= TEXBLENDOP_ADDSIGNED
;
211 blendop
= TEXBLENDOP_BLEND
;
214 blendop
= TEXBLENDOP_SUBTRACT
;
216 case GL_DOT3_RGB_EXT
:
218 blendop
= TEXBLENDOP_DOT3
;
220 case GL_DOT3_RGBA_EXT
:
222 blendop
= TEXBLENDOP_DOT3
;
225 return pass_through( state
, blendUnit
);
228 blendop
|= (rgb_shift
<< TEXOP_SCALE_SHIFT
);
231 /* Handle RGB args */
232 for(i
= 0; i
< 3; i
++) {
233 switch(combine
->SourceRGB
[i
]) {
235 args_RGB
[i
] = texel_op
;
241 args_RGB
[i
] = GetTexelOp( combine
->SourceRGB
[i
] - GL_TEXTURE0
);
244 args_RGB
[i
] = TEXBLENDARG_FACTOR_N
;
247 case GL_PRIMARY_COLOR
:
248 args_RGB
[i
] = TEXBLENDARG_DIFFUSE
;
251 args_RGB
[i
] = TEXBLENDARG_CURRENT
;
254 return pass_through( state
, blendUnit
);
257 switch(combine
->OperandRGB
[i
]) {
261 case GL_ONE_MINUS_SRC_COLOR
:
262 args_RGB
[i
] |= TEXBLENDARG_INV_ARG
;
265 args_RGB
[i
] |= TEXBLENDARG_REPLICATE_ALPHA
;
267 case GL_ONE_MINUS_SRC_ALPHA
:
268 args_RGB
[i
] |= (TEXBLENDARG_REPLICATE_ALPHA
|
269 TEXBLENDARG_INV_ARG
);
272 return pass_through( state
, blendUnit
);
277 /* Need to knobble the alpha calculations of TEXBLENDOP_DOT4 to
278 * match the spec. Can't use DOT3 as it won't propogate values
279 * into alpha as required:
281 * Note - the global factor is set up with alpha == .5, so
282 * the alpha part of the DOT4 calculation should be zero.
284 if ( combine
->ModeRGB
== GL_DOT3_RGBA_EXT
||
285 combine
->ModeRGB
== GL_DOT3_RGBA
) {
286 ablendop
= TEXBLENDOP_DOT4
;
287 args_A
[0] = TEXBLENDARG_FACTOR
; /* the global factor */
288 args_A
[1] = TEXBLENDARG_FACTOR
;
289 args_A
[2] = TEXBLENDARG_FACTOR
;
292 switch(combine
->ModeA
) {
294 ablendop
= TEXBLENDOP_ARG1
;
297 ablendop
= TEXBLENDOP_MODULATE
;
300 ablendop
= TEXBLENDOP_ADD
;
303 ablendop
= TEXBLENDOP_ADDSIGNED
;
306 ablendop
= TEXBLENDOP_BLEND
;
309 ablendop
= TEXBLENDOP_SUBTRACT
;
312 return pass_through( state
, blendUnit
);
316 ablendop
|= (alpha_shift
<< TEXOP_SCALE_SHIFT
);
319 for(i
= 0; i
< 3; i
++) {
320 switch(combine
->SourceA
[i
]) {
322 args_A
[i
] = texel_op
;
328 args_A
[i
] = GetTexelOp( combine
->SourceA
[i
] - GL_TEXTURE0
);
331 args_A
[i
] = TEXBLENDARG_FACTOR_N
;
334 case GL_PRIMARY_COLOR
:
335 args_A
[i
] = TEXBLENDARG_DIFFUSE
;
338 args_A
[i
] = TEXBLENDARG_CURRENT
;
341 return pass_through( state
, blendUnit
);
344 switch(combine
->OperandA
[i
]) {
348 case GL_ONE_MINUS_SRC_ALPHA
:
349 args_A
[i
] |= TEXBLENDARG_INV_ARG
;
352 return pass_through( state
, blendUnit
);
359 /* Native Arg1 == Arg0 in GL_EXT_texture_env_combine spec */
360 /* Native Arg2 == Arg1 in GL_EXT_texture_env_combine spec */
361 /* Native Arg0 == Arg2 in GL_EXT_texture_env_combine spec */
363 /* When we render we need to figure out which is the last really enabled
364 * tex unit, and put last stage on it
368 /* Build color & alpha pipelines */
371 state
[used
++] = (_3DSTATE_MAP_BLEND_OP_CMD(blendUnit
) |
373 ENABLE_TEXOUTPUT_WRT_SEL
|
374 TEXOP_OUTPUT_CURRENT
|
375 DISABLE_TEX_CNTRL_STAGE
|
378 state
[used
++] = (_3DSTATE_MAP_BLEND_OP_CMD(blendUnit
) |
380 ENABLE_TEXOUTPUT_WRT_SEL
|
381 TEXOP_OUTPUT_CURRENT
|
385 for ( i
= 0 ; i
< numColorArgs
; i
++ ) {
386 state
[used
++] = (_3DSTATE_MAP_BLEND_ARG_CMD(blendUnit
) |
387 tex_blend_rgb
[i
] | args_RGB
[i
]);
390 for ( i
= 0 ; i
< numAlphaArgs
; i
++ ) {
391 state
[used
++] = (_3DSTATE_MAP_BLEND_ARG_CMD(blendUnit
) |
392 tex_blend_a
[i
] | args_A
[i
]);
397 return emit_factor( blendUnit
, state
, used
, factor
);
403 static void emit_texblend( i830ContextPtr i830
, GLuint unit
, GLuint blendUnit
,
404 GLboolean last_stage
)
406 struct gl_texture_unit
*texUnit
= &i830
->intel
.ctx
.Texture
.Unit
[unit
];
407 struct gl_texture_object
*tObj
= texUnit
->_Current
;
408 i830TextureObjectPtr t
= (i830TextureObjectPtr
)tObj
->DriverData
;
409 GLuint tmp
[I830_TEXBLEND_SIZE
], tmp_sz
;
412 if (0) fprintf(stderr
, "%s unit %d\n", __FUNCTION__
, unit
);
414 /* Update i830->state.TexBlend
416 tmp_sz
= i830SetTexEnvCombine(i830
, texUnit
->_CurrentCombine
, blendUnit
,
417 GetTexelOp(unit
), tmp
,
421 tmp
[0] |= TEXOP_LAST_STAGE
;
423 if (tmp_sz
!= i830
->state
.TexBlendWordsUsed
[blendUnit
] ||
424 memcmp( tmp
, i830
->state
.TexBlend
[blendUnit
], tmp_sz
* sizeof(GLuint
))) {
426 I830_STATECHANGE( i830
, I830_UPLOAD_TEXBLEND(blendUnit
) );
427 memcpy( i830
->state
.TexBlend
[blendUnit
], tmp
, tmp_sz
* sizeof(GLuint
));
428 i830
->state
.TexBlendWordsUsed
[blendUnit
] = tmp_sz
;
431 I830_ACTIVESTATE(i830
, I830_UPLOAD_TEXBLEND(blendUnit
), GL_TRUE
);
434 static void emit_passthrough( i830ContextPtr i830
)
436 GLuint tmp
[I830_TEXBLEND_SIZE
], tmp_sz
;
439 tmp_sz
= pass_through( tmp
, unit
);
440 tmp
[0] |= TEXOP_LAST_STAGE
;
442 if (tmp_sz
!= i830
->state
.TexBlendWordsUsed
[unit
] ||
443 memcmp( tmp
, i830
->state
.TexBlend
[unit
], tmp_sz
* sizeof(GLuint
))) {
445 I830_STATECHANGE( i830
, I830_UPLOAD_TEXBLEND(unit
) );
446 memcpy( i830
->state
.TexBlend
[unit
], tmp
, tmp_sz
* sizeof(GLuint
));
447 i830
->state
.TexBlendWordsUsed
[unit
] = tmp_sz
;
450 I830_ACTIVESTATE(i830
, I830_UPLOAD_TEXBLEND(unit
), GL_TRUE
);
453 void i830EmitTextureBlend( i830ContextPtr i830
)
455 GLcontext
*ctx
= &i830
->intel
.ctx
;
456 GLuint unit
, last_stage
= 0, blendunit
= 0;
458 I830_ACTIVESTATE(i830
, I830_UPLOAD_TEXBLEND_ALL
, GL_FALSE
);
460 if (ctx
->Texture
._EnabledUnits
) {
461 for (unit
= 0 ; unit
< ctx
->Const
.MaxTextureUnits
; unit
++)
462 if (ctx
->Texture
.Unit
[unit
]._ReallyEnabled
)
465 for (unit
= 0 ; unit
< ctx
->Const
.MaxTextureUnits
; unit
++)
466 if (ctx
->Texture
.Unit
[unit
]._ReallyEnabled
)
467 emit_texblend( i830
, unit
, blendunit
++, last_stage
== unit
);
470 emit_passthrough( i830
);