1 /**************************************************************************
3 * Copyright 2003 VMware, Inc.
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 VMWARE 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 **************************************************************************/
28 #include "main/glheader.h"
29 #include "main/macros.h"
30 #include "main/mtypes.h"
31 #include "main/simple_list.h"
32 #include "main/enums.h"
35 #include "intel_screen.h"
36 #include "intel_tex.h"
38 #include "i830_context.h"
42 /* ================================================================
43 * Texture combine functions
46 pass_through(GLuint
* state
, GLuint blendUnit
)
48 state
[0] = (_3DSTATE_MAP_BLEND_OP_CMD(blendUnit
) |
50 ENABLE_TEXOUTPUT_WRT_SEL
|
51 TEXOP_OUTPUT_CURRENT
|
52 DISABLE_TEX_CNTRL_STAGE
|
53 TEXOP_SCALE_1X
| TEXOP_MODIFY_PARMS
| TEXBLENDOP_ARG1
);
54 state
[1] = (_3DSTATE_MAP_BLEND_OP_CMD(blendUnit
) |
56 ENABLE_TEXOUTPUT_WRT_SEL
|
57 TEXOP_OUTPUT_CURRENT
|
58 TEXOP_SCALE_1X
| TEXOP_MODIFY_PARMS
| TEXBLENDOP_ARG1
);
59 state
[2] = (_3DSTATE_MAP_BLEND_ARG_CMD(blendUnit
) |
62 TEXBLENDARG_MODIFY_PARMS
| TEXBLENDARG_CURRENT
);
63 state
[3] = (_3DSTATE_MAP_BLEND_ARG_CMD(blendUnit
) |
66 TEXBLENDARG_MODIFY_PARMS
| TEXBLENDARG_CURRENT
);
72 emit_factor(GLuint blendUnit
, GLuint
* state
, GLuint count
,
73 const GLfloat
* factor
)
79 fprintf(stderr
, "emit constant %d: %.2f %.2f %.2f %.2f\n",
80 blendUnit
, factor
[0], factor
[1], factor
[2], factor
[3]);
82 UNCLAMPED_FLOAT_TO_UBYTE(r
, factor
[0]);
83 UNCLAMPED_FLOAT_TO_UBYTE(g
, factor
[1]);
84 UNCLAMPED_FLOAT_TO_UBYTE(b
, factor
[2]);
85 UNCLAMPED_FLOAT_TO_UBYTE(a
, factor
[3]);
87 col
= ((a
<< 24) | (r
<< 16) | (g
<< 8) | b
);
89 state
[count
++] = _3DSTATE_COLOR_FACTOR_N_CMD(blendUnit
);
97 GetTexelOp(GLint unit
)
101 return TEXBLENDARG_TEXEL0
;
103 return TEXBLENDARG_TEXEL1
;
105 return TEXBLENDARG_TEXEL2
;
107 return TEXBLENDARG_TEXEL3
;
109 return TEXBLENDARG_TEXEL0
;
115 * Calculate the hardware instuctions to setup the current texture enviromnemt
116 * settings. Since \c gl_texture_unit::_CurrentCombine is used, both
117 * "classic" texture enviroments and GL_ARB_texture_env_combine type texture
118 * environments are treated identically.
121 * This function should return \c bool. When \c false is returned,
122 * it means that an environment is selected that the hardware cannot do. This
123 * is the way the Radeon and R200 drivers work.
126 * Looking at i830_3d_regs.h, it seems the i830 can do part of
127 * GL_ATI_texture_env_combine3. It can handle using \c GL_ONE and
128 * \c GL_ZERO as combine inputs (which the code already supports). It can
129 * also handle the \c GL_MODULATE_ADD_ATI mode. Is it worth investigating
130 * partial support for the extension?
133 i830SetTexEnvCombine(struct i830_context
* i830
,
134 const struct gl_tex_env_combine_state
* combine
,
136 GLuint texel_op
, GLuint
* state
, const GLfloat
* factor
)
138 const GLuint numColorArgs
= combine
->_NumArgsRGB
;
139 const GLuint numAlphaArgs
= combine
->_NumArgsA
;
147 bool need_factor
= 0;
150 static const GLuint tex_blend_rgb
[3] = {
151 TEXPIPE_COLOR
| TEXBLEND_ARG1
| TEXBLENDARG_MODIFY_PARMS
,
152 TEXPIPE_COLOR
| TEXBLEND_ARG2
| TEXBLENDARG_MODIFY_PARMS
,
153 TEXPIPE_COLOR
| TEXBLEND_ARG0
| TEXBLENDARG_MODIFY_PARMS
,
155 static const GLuint tex_blend_a
[3] = {
156 TEXPIPE_ALPHA
| TEXBLEND_ARG1
| TEXBLENDARG_MODIFY_PARMS
,
157 TEXPIPE_ALPHA
| TEXBLEND_ARG2
| TEXBLENDARG_MODIFY_PARMS
,
158 TEXPIPE_ALPHA
| TEXBLEND_ARG0
| TEXBLENDARG_MODIFY_PARMS
,
161 if (INTEL_DEBUG
& DEBUG_TEXTURE
)
162 fprintf(stderr
, "%s\n", __FUNCTION__
);
165 /* The EXT version of the DOT3 extension does not support the
166 * scale factor, but the ARB version (and the version in OpenGL
169 switch (combine
->ModeRGB
) {
170 case GL_DOT3_RGB_EXT
:
171 alpha_shift
= combine
->ScaleShiftA
;
175 case GL_DOT3_RGBA_EXT
:
181 rgb_shift
= combine
->ScaleShiftRGB
;
182 alpha_shift
= combine
->ScaleShiftA
;
187 switch (combine
->ModeRGB
) {
189 blendop
= TEXBLENDOP_ARG1
;
192 blendop
= TEXBLENDOP_MODULATE
;
195 blendop
= TEXBLENDOP_ADD
;
198 blendop
= TEXBLENDOP_ADDSIGNED
;
201 blendop
= TEXBLENDOP_BLEND
;
204 blendop
= TEXBLENDOP_SUBTRACT
;
206 case GL_DOT3_RGB_EXT
:
208 blendop
= TEXBLENDOP_DOT3
;
210 case GL_DOT3_RGBA_EXT
:
212 blendop
= TEXBLENDOP_DOT3
;
215 return pass_through(state
, blendUnit
);
218 blendop
|= (rgb_shift
<< TEXOP_SCALE_SHIFT
);
221 /* Handle RGB args */
222 for (i
= 0; i
< 3; i
++) {
223 switch (combine
->SourceRGB
[i
]) {
225 args_RGB
[i
] = texel_op
;
231 args_RGB
[i
] = GetTexelOp(combine
->SourceRGB
[i
] - GL_TEXTURE0
);
234 args_RGB
[i
] = TEXBLENDARG_FACTOR_N
;
237 case GL_PRIMARY_COLOR
:
238 args_RGB
[i
] = TEXBLENDARG_DIFFUSE
;
241 args_RGB
[i
] = TEXBLENDARG_CURRENT
;
244 return pass_through(state
, blendUnit
);
247 switch (combine
->OperandRGB
[i
]) {
251 case GL_ONE_MINUS_SRC_COLOR
:
252 args_RGB
[i
] |= TEXBLENDARG_INV_ARG
;
255 args_RGB
[i
] |= TEXBLENDARG_REPLICATE_ALPHA
;
257 case GL_ONE_MINUS_SRC_ALPHA
:
258 args_RGB
[i
] |= (TEXBLENDARG_REPLICATE_ALPHA
| TEXBLENDARG_INV_ARG
);
261 return pass_through(state
, blendUnit
);
266 /* Need to knobble the alpha calculations of TEXBLENDOP_DOT4 to
267 * match the spec. Can't use DOT3 as it won't propogate values
268 * into alpha as required:
270 * Note - the global factor is set up with alpha == .5, so
271 * the alpha part of the DOT4 calculation should be zero.
273 if (combine
->ModeRGB
== GL_DOT3_RGBA_EXT
||
274 combine
->ModeRGB
== GL_DOT3_RGBA
) {
275 ablendop
= TEXBLENDOP_DOT4
;
276 args_A
[0] = TEXBLENDARG_FACTOR
; /* the global factor */
277 args_A
[1] = TEXBLENDARG_FACTOR
;
278 args_A
[2] = TEXBLENDARG_FACTOR
;
281 switch (combine
->ModeA
) {
283 ablendop
= TEXBLENDOP_ARG1
;
286 ablendop
= TEXBLENDOP_MODULATE
;
289 ablendop
= TEXBLENDOP_ADD
;
292 ablendop
= TEXBLENDOP_ADDSIGNED
;
295 ablendop
= TEXBLENDOP_BLEND
;
298 ablendop
= TEXBLENDOP_SUBTRACT
;
301 return pass_through(state
, blendUnit
);
305 ablendop
|= (alpha_shift
<< TEXOP_SCALE_SHIFT
);
308 for (i
= 0; i
< 3; i
++) {
309 switch (combine
->SourceA
[i
]) {
311 args_A
[i
] = texel_op
;
317 args_A
[i
] = GetTexelOp(combine
->SourceA
[i
] - GL_TEXTURE0
);
320 args_A
[i
] = TEXBLENDARG_FACTOR_N
;
323 case GL_PRIMARY_COLOR
:
324 args_A
[i
] = TEXBLENDARG_DIFFUSE
;
327 args_A
[i
] = TEXBLENDARG_CURRENT
;
330 return pass_through(state
, blendUnit
);
333 switch (combine
->OperandA
[i
]) {
337 case GL_ONE_MINUS_SRC_ALPHA
:
338 args_A
[i
] |= TEXBLENDARG_INV_ARG
;
341 return pass_through(state
, blendUnit
);
348 /* Native Arg1 == Arg0 in GL_EXT_texture_env_combine spec */
349 /* Native Arg2 == Arg1 in GL_EXT_texture_env_combine spec */
350 /* Native Arg0 == Arg2 in GL_EXT_texture_env_combine spec */
352 /* When we render we need to figure out which is the last really enabled
353 * tex unit, and put last stage on it
357 /* Build color & alpha pipelines */
360 state
[used
++] = (_3DSTATE_MAP_BLEND_OP_CMD(blendUnit
) |
362 ENABLE_TEXOUTPUT_WRT_SEL
|
363 TEXOP_OUTPUT_CURRENT
|
364 DISABLE_TEX_CNTRL_STAGE
| TEXOP_MODIFY_PARMS
| blendop
);
365 state
[used
++] = (_3DSTATE_MAP_BLEND_OP_CMD(blendUnit
) |
367 ENABLE_TEXOUTPUT_WRT_SEL
|
368 TEXOP_OUTPUT_CURRENT
| TEXOP_MODIFY_PARMS
| ablendop
);
370 for (i
= 0; i
< numColorArgs
; i
++) {
371 state
[used
++] = (_3DSTATE_MAP_BLEND_ARG_CMD(blendUnit
) |
372 tex_blend_rgb
[i
] | args_RGB
[i
]);
375 for (i
= 0; i
< numAlphaArgs
; i
++) {
376 state
[used
++] = (_3DSTATE_MAP_BLEND_ARG_CMD(blendUnit
) |
377 tex_blend_a
[i
] | args_A
[i
]);
382 return emit_factor(blendUnit
, state
, used
, factor
);
389 emit_texblend(struct i830_context
*i830
, GLuint unit
, GLuint blendUnit
,
392 struct gl_texture_unit
*texUnit
= &i830
->intel
.ctx
.Texture
.Unit
[unit
];
393 GLuint tmp
[I830_TEXBLEND_SIZE
], tmp_sz
;
397 fprintf(stderr
, "%s unit %d\n", __FUNCTION__
, unit
);
399 /* Update i830->state.TexBlend
401 tmp_sz
= i830SetTexEnvCombine(i830
, texUnit
->_CurrentCombine
, blendUnit
,
402 GetTexelOp(unit
), tmp
, texUnit
->EnvColor
);
405 tmp
[0] |= TEXOP_LAST_STAGE
;
407 if (tmp_sz
!= i830
->state
.TexBlendWordsUsed
[blendUnit
] ||
408 memcmp(tmp
, i830
->state
.TexBlend
[blendUnit
],
409 tmp_sz
* sizeof(GLuint
))) {
411 I830_STATECHANGE(i830
, I830_UPLOAD_TEXBLEND(blendUnit
));
412 memcpy(i830
->state
.TexBlend
[blendUnit
], tmp
, tmp_sz
* sizeof(GLuint
));
413 i830
->state
.TexBlendWordsUsed
[blendUnit
] = tmp_sz
;
416 I830_ACTIVESTATE(i830
, I830_UPLOAD_TEXBLEND(blendUnit
), true);
420 emit_passthrough(struct i830_context
*i830
)
422 GLuint tmp
[I830_TEXBLEND_SIZE
], tmp_sz
;
425 tmp_sz
= pass_through(tmp
, unit
);
426 tmp
[0] |= TEXOP_LAST_STAGE
;
428 if (tmp_sz
!= i830
->state
.TexBlendWordsUsed
[unit
] ||
429 memcmp(tmp
, i830
->state
.TexBlend
[unit
], tmp_sz
* sizeof(GLuint
))) {
431 I830_STATECHANGE(i830
, I830_UPLOAD_TEXBLEND(unit
));
432 memcpy(i830
->state
.TexBlend
[unit
], tmp
, tmp_sz
* sizeof(GLuint
));
433 i830
->state
.TexBlendWordsUsed
[unit
] = tmp_sz
;
436 I830_ACTIVESTATE(i830
, I830_UPLOAD_TEXBLEND(unit
), true);
440 i830EmitTextureBlend(struct i830_context
*i830
)
442 struct gl_context
*ctx
= &i830
->intel
.ctx
;
443 GLuint unit
, last_stage
= 0, blendunit
= 0;
445 I830_ACTIVESTATE(i830
, I830_UPLOAD_TEXBLEND_ALL
, false);
447 if (ctx
->Texture
._EnabledUnits
) {
448 for (unit
= 0; unit
< ctx
->Const
.MaxTextureUnits
; unit
++)
449 if (ctx
->Texture
.Unit
[unit
]._ReallyEnabled
)
452 for (unit
= 0; unit
< ctx
->Const
.MaxTextureUnits
; unit
++)
453 if (ctx
->Texture
.Unit
[unit
]._ReallyEnabled
)
454 emit_texblend(i830
, unit
, blendunit
++, last_stage
== unit
);
457 emit_passthrough(i830
);