summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoland Scheidegger <sroland@vmware.com>2009-03-12 15:01:16 +0100
committerRoland Scheidegger <sroland@vmware.com>2009-03-12 15:01:16 +0100
commit114152e068ec919feb0a57a1259c2ada970b9f02 (patch)
treef424d1c9f88ddf36c94991906879f3a71ca1c36a
parentb7d841b59e9087c0ba8c2726897ab1506375e4e6 (diff)
mesa: add support for ATI_envmap_bumpmap
add new entrypoints, new texture format, etc translate in texenvprogram.c for drivers using the mesa-generated tex env fragment program also handled in swrast, but not tested (cannot work due to negative texel results not handled correctly)
-rw-r--r--src/mesa/glapi/gl_API.xml50
-rw-r--r--src/mesa/main/api_exec.c6
-rw-r--r--src/mesa/main/config.h3
-rw-r--r--src/mesa/main/context.c3
-rw-r--r--src/mesa/main/dlist.c46
-rw-r--r--src/mesa/main/extensions.c2
-rw-r--r--src/mesa/main/image.c153
-rw-r--r--src/mesa/main/image.h7
-rw-r--r--src/mesa/main/macros.h7
-rw-r--r--src/mesa/main/mipmap.c14
-rw-r--r--src/mesa/main/mtypes.h5
-rw-r--r--src/mesa/main/texenv.c174
-rw-r--r--src/mesa/main/texenv.h11
-rw-r--r--src/mesa/main/texenvprogram.c99
-rw-r--r--src/mesa/main/texformat.c42
-rw-r--r--src/mesa/main/texformat.h14
-rw-r--r--src/mesa/main/texformat_tmp.h17
-rw-r--r--src/mesa/main/teximage.c39
-rw-r--r--src/mesa/main/texstate.c20
-rw-r--r--src/mesa/main/texstore.c91
-rw-r--r--src/mesa/main/texstore.h2
-rw-r--r--src/mesa/shader/prog_statevars.c28
-rw-r--r--src/mesa/shader/prog_statevars.h2
-rw-r--r--src/mesa/swrast/s_texcombine.c95
24 files changed, 906 insertions, 24 deletions
diff --git a/src/mesa/glapi/gl_API.xml b/src/mesa/glapi/gl_API.xml
index 8212fc24770..cc3e3ae6bff 100644
--- a/src/mesa/glapi/gl_API.xml
+++ b/src/mesa/glapi/gl_API.xml
@@ -11681,6 +11681,56 @@
11681 <enum name="DEPTH_STENCIL_TO_BGRA_NV" value="0x886F"/> 11681 <enum name="DEPTH_STENCIL_TO_BGRA_NV" value="0x886F"/>
11682</category> 11682</category>
11683 11683
11684<category name="GL_ATI_envmap_bumpmap" number="244">
11685 <enum name="BUMP_ROT_MATRIX_ATI" count="4" value="0x8775">
11686 <size name="TexBumpParameterfv"/>
11687 <size name="TexBumpParameteriv"/>
11688 <size name="GetTexBumpParameterfv" mode="get"/>
11689 <size name="GetTexBumpParameteriv" mode="get"/>
11690 </enum>
11691 <enum name="BUMP_ROT_MATRIX_SIZE_ATI" count="1" value="0x8776">
11692 <size name="GetTexBumpParameterfv" mode="get"/>
11693 <size name="GetTexBumpParameteriv" mode="get"/>
11694 </enum>
11695 <enum name="BUMP_NUM_TEX_UNITS_ATI" count="1" value="0x8777">
11696 <size name="GetTexBumpParameterfv" mode="get"/>
11697 <size name="GetTexBumpParameteriv" mode="get"/>
11698 </enum>
11699 <enum name="BUMP_TEX_UNITS_ATI" count="-1" value="0x8778">
11700 <size name="GetTexBumpParameterfv" mode="get"/>
11701 <size name="GetTexBumpParameteriv" mode="get"/>
11702 </enum>
11703 <enum name="DUDV_ATI" value="0x8779"/>
11704 <enum name="DU8DV8_ATI" value="0x877A"/>
11705 <enum name="BUMP_ENVMAP_ATI" value="0x877B"/>
11706 <enum name="BUMP_TARGET_ATI" count="1" value="0x877C">
11707 <size name="TexEnviv"/>
11708 <size name="TexEnvfv"/>
11709 <size name="GetTexEnviv" mode="get"/>
11710 <size name="GetTexEnvfv" mode="get"/>
11711 </enum>
11712 <function name="TexBumpParameterfvATI" offset="assign">
11713 <param name="pname" type="GLenum"/>
11714 <param name="param" type="const GLfloat *" variable_param="pname"/>
11715 <glx ignore="true"/>
11716 </function>
11717 <function name="TexBumpParameterivATI" offset="assign">
11718 <param name="pname" type="GLenum"/>
11719 <param name="param" type="const GLint *" variable_param="pname"/>
11720 <glx ignore="true"/>
11721 </function>
11722 <function name="GetTexBumpParameterfvATI" offset="assign">
11723 <param name="pname" type="GLenum"/>
11724 <param name="param" type="GLfloat *" variable_param="pname"/>
11725 <glx ignore="true"/>
11726 </function>
11727 <function name="GetTexBumpParameterivATI" offset="assign">
11728 <param name="pname" type="GLenum"/>
11729 <param name="param" type="GLint *" variable_param="pname"/>
11730 <glx ignore="true"/>
11731 </function>
11732</category>
11733
11684<category name="GL_ATI_fragment_shader" number="245"> 11734<category name="GL_ATI_fragment_shader" number="245">
11685 <function name="GenFragmentShadersATI" offset="assign"> 11735 <function name="GenFragmentShadersATI" offset="assign">
11686 <return type="GLuint"/> 11736 <return type="GLuint"/>
diff --git a/src/mesa/main/api_exec.c b/src/mesa/main/api_exec.c
index e0715817add..6f66ff47a08 100644
--- a/src/mesa/main/api_exec.c
+++ b/src/mesa/main/api_exec.c
@@ -839,6 +839,12 @@ _mesa_init_exec_table(struct _glapi_table *exec)
839 SET_SetFragmentShaderConstantATI(exec, _mesa_SetFragmentShaderConstantATI); 839 SET_SetFragmentShaderConstantATI(exec, _mesa_SetFragmentShaderConstantATI);
840#endif 840#endif
841 841
842 /* GL_ATI_envmap_bumpmap */
843 SET_GetTexBumpParameterivATI(exec, _mesa_GetTexBumpParameterivATI);
844 SET_GetTexBumpParameterfvATI(exec, _mesa_GetTexBumpParameterfvATI);
845 SET_TexBumpParameterivATI(exec, _mesa_TexBumpParameterivATI);
846 SET_TexBumpParameterfvATI(exec, _mesa_TexBumpParameterfvATI);
847
842#if FEATURE_EXT_framebuffer_object 848#if FEATURE_EXT_framebuffer_object
843 SET_IsRenderbufferEXT(exec, _mesa_IsRenderbufferEXT); 849 SET_IsRenderbufferEXT(exec, _mesa_IsRenderbufferEXT);
844 SET_BindRenderbufferEXT(exec, _mesa_BindRenderbufferEXT); 850 SET_BindRenderbufferEXT(exec, _mesa_BindRenderbufferEXT);
diff --git a/src/mesa/main/config.h b/src/mesa/main/config.h
index 282ad9514c2..fc31155b35b 100644
--- a/src/mesa/main/config.h
+++ b/src/mesa/main/config.h
@@ -232,7 +232,8 @@
232#define MAX_COLOR_ATTACHMENTS 8 232#define MAX_COLOR_ATTACHMENTS 8
233/*@}*/ 233/*@}*/
234 234
235 235/** For GL_ATI_envmap_bump - support bump mapping on first 8 units */
236#define SUPPORTED_ATI_BUMP_UNITS 0xff
236 237
237/** 238/**
238 * \name Mesa-specific parameters 239 * \name Mesa-specific parameters
diff --git a/src/mesa/main/context.c b/src/mesa/main/context.c
index 9fd9e769d29..84bf0205a8e 100644
--- a/src/mesa/main/context.c
+++ b/src/mesa/main/context.c
@@ -589,6 +589,9 @@ _mesa_init_constants(GLcontext *ctx)
589 /* GL_ARB_framebuffer_object */ 589 /* GL_ARB_framebuffer_object */
590 ctx->Const.MaxSamples = 0; 590 ctx->Const.MaxSamples = 0;
591 591
592 /* GL_ATI_envmap_bumpmap */
593 ctx->Const.SupportedBumpUnits = SUPPORTED_ATI_BUMP_UNITS;
594
592 /* sanity checks */ 595 /* sanity checks */
593 ASSERT(ctx->Const.MaxTextureUnits == MIN2(ctx->Const.MaxTextureImageUnits, 596 ASSERT(ctx->Const.MaxTextureUnits == MIN2(ctx->Const.MaxTextureImageUnits,
594 ctx->Const.MaxTextureCoordUnits)); 597 ctx->Const.MaxTextureCoordUnits));
diff --git a/src/mesa/main/dlist.c b/src/mesa/main/dlist.c
index d4bd56be83a..ebcef0268a4 100644
--- a/src/mesa/main/dlist.c
+++ b/src/mesa/main/dlist.c
@@ -320,6 +320,8 @@ typedef enum
320 /* GL_ARB_draw_buffers */ 320 /* GL_ARB_draw_buffers */
321 OPCODE_DRAW_BUFFERS_ARB, 321 OPCODE_DRAW_BUFFERS_ARB,
322 /* GL_ATI_fragment_shader */ 322 /* GL_ATI_fragment_shader */
323 OPCODE_TEX_BUMP_PARAMETER_ATI,
324 /* GL_ATI_fragment_shader */
323 OPCODE_BIND_FRAGMENT_SHADER_ATI, 325 OPCODE_BIND_FRAGMENT_SHADER_ATI,
324 OPCODE_SET_FRAGMENT_SHADER_CONSTANTS_ATI, 326 OPCODE_SET_FRAGMENT_SHADER_CONSTANTS_ATI,
325 /* OpenGL 2.0 */ 327 /* OpenGL 2.0 */
@@ -4803,6 +4805,36 @@ save_DrawBuffersARB(GLsizei count, const GLenum * buffers)
4803 } 4805 }
4804} 4806}
4805 4807
4808static void GLAPIENTRY
4809save_TexBumpParameterfvATI(GLenum pname, const GLfloat *param)
4810{
4811 GET_CURRENT_CONTEXT(ctx);
4812 Node *n;
4813
4814 n = ALLOC_INSTRUCTION(ctx, OPCODE_TEX_BUMP_PARAMETER_ATI, 5);
4815 if (n) {
4816 n[1].ui = pname;
4817 n[2].f = param[0];
4818 n[3].f = param[1];
4819 n[4].f = param[2];
4820 n[5].f = param[3];
4821 }
4822 if (ctx->ExecuteFlag) {
4823 CALL_TexBumpParameterfvATI(ctx->Exec, (pname, param));
4824 }
4825}
4826
4827static void GLAPIENTRY
4828save_TexBumpParameterivATI(GLenum pname, const GLint *param)
4829{
4830 GLfloat p[4];
4831 p[0] = INT_TO_FLOAT(param[0]);
4832 p[1] = INT_TO_FLOAT(param[1]);
4833 p[2] = INT_TO_FLOAT(param[2]);
4834 p[3] = INT_TO_FLOAT(param[3]);
4835 save_TexBumpParameterfvATI(pname, p);
4836}
4837
4806#if FEATURE_ATI_fragment_shader 4838#if FEATURE_ATI_fragment_shader
4807static void GLAPIENTRY 4839static void GLAPIENTRY
4808save_BindFragmentShaderATI(GLuint id) 4840save_BindFragmentShaderATI(GLuint id)
@@ -6505,6 +6537,16 @@ execute_list(GLcontext *ctx, GLuint list)
6505 n[9].i, n[10].e)); 6537 n[9].i, n[10].e));
6506 break; 6538 break;
6507#endif 6539#endif
6540 case OPCODE_TEX_BUMP_PARAMETER_ATI:
6541 {
6542 GLfloat values[4];
6543 GLuint i, pname = n[1].ui;
6544
6545 for (i = 0; i < 4; i++)
6546 values[i] = n[1 + i].f;
6547 CALL_TexBumpParameterfvATI(ctx->Exec, (pname, values));
6548 }
6549 break;
6508#if FEATURE_ATI_fragment_shader 6550#if FEATURE_ATI_fragment_shader
6509 case OPCODE_BIND_FRAGMENT_SHADER_ATI: 6551 case OPCODE_BIND_FRAGMENT_SHADER_ATI:
6510 CALL_BindFragmentShaderATI(ctx->Exec, (n[1].i)); 6552 CALL_BindFragmentShaderATI(ctx->Exec, (n[1].i));
@@ -8043,6 +8085,10 @@ _mesa_init_dlist_table(struct _glapi_table *table)
8043 SET_VertexAttribPointerNV(table, _mesa_VertexAttribPointerNV); 8085 SET_VertexAttribPointerNV(table, _mesa_VertexAttribPointerNV);
8044#endif 8086#endif
8045 8087
8088 /* 244. GL_ATI_envmap_bumpmap */
8089 SET_TexBumpParameterivATI(table, save_TexBumpParameterivATI);
8090 SET_TexBumpParameterfvATI(table, save_TexBumpParameterfvATI);
8091
8046 /* 245. GL_ATI_fragment_shader */ 8092 /* 245. GL_ATI_fragment_shader */
8047#if FEATURE_ATI_fragment_shader 8093#if FEATURE_ATI_fragment_shader
8048 SET_BindFragmentShaderATI(table, save_BindFragmentShaderATI); 8094 SET_BindFragmentShaderATI(table, save_BindFragmentShaderATI);
diff --git a/src/mesa/main/extensions.c b/src/mesa/main/extensions.c
index fbca924ad3d..2d2bf517843 100644
--- a/src/mesa/main/extensions.c
+++ b/src/mesa/main/extensions.c
@@ -137,6 +137,7 @@ static const struct {
137 { ON, "GL_APPLE_packed_pixels", F(APPLE_packed_pixels) }, 137 { ON, "GL_APPLE_packed_pixels", F(APPLE_packed_pixels) },
138 { OFF, "GL_APPLE_vertex_array_object", F(APPLE_vertex_array_object) }, 138 { OFF, "GL_APPLE_vertex_array_object", F(APPLE_vertex_array_object) },
139 { OFF, "GL_ATI_blend_equation_separate", F(EXT_blend_equation_separate) }, 139 { OFF, "GL_ATI_blend_equation_separate", F(EXT_blend_equation_separate) },
140 { OFF, "GL_ATI_envmap_bumpmap", F(ATI_envmap_bumpmap) },
140 { OFF, "GL_ATI_texture_env_combine3", F(ATI_texture_env_combine3)}, 141 { OFF, "GL_ATI_texture_env_combine3", F(ATI_texture_env_combine3)},
141 { OFF, "GL_ATI_texture_mirror_once", F(ATI_texture_mirror_once)}, 142 { OFF, "GL_ATI_texture_mirror_once", F(ATI_texture_mirror_once)},
142 { OFF, "GL_ATI_fragment_shader", F(ATI_fragment_shader)}, 143 { OFF, "GL_ATI_fragment_shader", F(ATI_fragment_shader)},
@@ -229,6 +230,7 @@ _mesa_enable_sw_extensions(GLcontext *ctx)
229 /*ctx->Extensions.ARB_vertex_buffer_object = GL_TRUE;*/ 230 /*ctx->Extensions.ARB_vertex_buffer_object = GL_TRUE;*/
230#endif 231#endif
231 ctx->Extensions.APPLE_vertex_array_object = GL_TRUE; 232 ctx->Extensions.APPLE_vertex_array_object = GL_TRUE;
233 ctx->Extensions.ATI_envmap_bumpmap = GL_TRUE;
232#if FEATURE_ATI_fragment_shader 234#if FEATURE_ATI_fragment_shader
233 ctx->Extensions.ATI_fragment_shader = GL_TRUE; 235 ctx->Extensions.ATI_fragment_shader = GL_TRUE;
234#endif 236#endif
diff --git a/src/mesa/main/image.c b/src/mesa/main/image.c
index 4d86c547775..ed0811660d2 100644
--- a/src/mesa/main/image.c
+++ b/src/mesa/main/image.c
@@ -293,6 +293,8 @@ _mesa_components_in_format( GLenum format )
293 return 2; 293 return 2;
294 case GL_DEPTH_STENCIL_EXT: 294 case GL_DEPTH_STENCIL_EXT:
295 return 2; 295 return 2;
296 case GL_DUDV_ATI:
297 return 2;
296 default: 298 default:
297 return -1; 299 return -1;
298 } 300 }
@@ -503,6 +505,20 @@ _mesa_is_legal_format_and_type( GLcontext *ctx, GLenum format, GLenum type )
503 return GL_TRUE; 505 return GL_TRUE;
504 else 506 else
505 return GL_FALSE; 507 return GL_FALSE;
508 case GL_DUDV_ATI:
509 case GL_DU8DV8_ATI:
510 switch (type) {
511 case GL_BYTE:
512 case GL_UNSIGNED_BYTE:
513 case GL_SHORT:
514 case GL_UNSIGNED_SHORT:
515 case GL_INT:
516 case GL_UNSIGNED_INT:
517 case GL_FLOAT:
518 return GL_TRUE;
519 default:
520 return GL_FALSE;
521 }
506 default: 522 default:
507 ; /* fall-through */ 523 ; /* fall-through */
508 } 524 }
@@ -1674,8 +1690,19 @@ _mesa_pack_rgba_span_float(GLcontext *ctx, GLuint n, GLfloat rgba[][4],
1674 GLfloat luminance[MAX_WIDTH]; 1690 GLfloat luminance[MAX_WIDTH];
1675 const GLint comps = _mesa_components_in_format(dstFormat); 1691 const GLint comps = _mesa_components_in_format(dstFormat);
1676 GLuint i; 1692 GLuint i;
1677 1693 /* clamping only applies to colors, not the dudv values, but still need
1678 if (dstType != GL_FLOAT || ctx->Color.ClampReadColor == GL_TRUE) { 1694 it if converting to unsigned values (which doesn't make much sense) */
1695 if (dstFormat == GL_DUDV_ATI || dstFormat == GL_DU8DV8_ATI) {
1696 switch (dstType) {
1697 case GL_UNSIGNED_BYTE:
1698 case GL_UNSIGNED_SHORT:
1699 case GL_UNSIGNED_INT:
1700 transferOps |= IMAGE_CLAMP_BIT;
1701 break;
1702 /* actually might want clamp to [-1,1] otherwise but shouldn't matter? */
1703 }
1704 }
1705 else if (dstType != GL_FLOAT || ctx->Color.ClampReadColor == GL_TRUE) {
1679 /* need to clamp to [0, 1] */ 1706 /* need to clamp to [0, 1] */
1680 transferOps |= IMAGE_CLAMP_BIT; 1707 transferOps |= IMAGE_CLAMP_BIT;
1681 } 1708 }
@@ -1774,6 +1801,13 @@ _mesa_pack_rgba_span_float(GLcontext *ctx, GLuint n, GLfloat rgba[][4],
1774 dst[i*4+3] = FLOAT_TO_UBYTE(rgba[i][RCOMP]); 1801 dst[i*4+3] = FLOAT_TO_UBYTE(rgba[i][RCOMP]);
1775 } 1802 }
1776 break; 1803 break;
1804 case GL_DUDV_ATI:
1805 case GL_DU8DV8_ATI:
1806 for (i=0;i<n;i++) {
1807 dst[i*2+0] = FLOAT_TO_UBYTE(rgba[i][RCOMP]);
1808 dst[i*2+1] = FLOAT_TO_UBYTE(rgba[i][GCOMP]);
1809 }
1810 break;
1777 default: 1811 default:
1778 _mesa_problem(ctx, "bad format in _mesa_pack_rgba_span\n"); 1812 _mesa_problem(ctx, "bad format in _mesa_pack_rgba_span\n");
1779 } 1813 }
@@ -1847,6 +1881,13 @@ _mesa_pack_rgba_span_float(GLcontext *ctx, GLuint n, GLfloat rgba[][4],
1847 dst[i*4+3] = FLOAT_TO_BYTE(rgba[i][RCOMP]); 1881 dst[i*4+3] = FLOAT_TO_BYTE(rgba[i][RCOMP]);
1848 } 1882 }
1849 break; 1883 break;
1884 case GL_DUDV_ATI:
1885 case GL_DU8DV8_ATI:
1886 for (i=0;i<n;i++) {
1887 dst[i*2+0] = FLOAT_TO_BYTE(rgba[i][RCOMP]);
1888 dst[i*2+1] = FLOAT_TO_BYTE(rgba[i][GCOMP]);
1889 }
1890 break;
1850 default: 1891 default:
1851 _mesa_problem(ctx, "bad format in _mesa_pack_rgba_span\n"); 1892 _mesa_problem(ctx, "bad format in _mesa_pack_rgba_span\n");
1852 } 1893 }
@@ -1920,6 +1961,13 @@ _mesa_pack_rgba_span_float(GLcontext *ctx, GLuint n, GLfloat rgba[][4],
1920 CLAMPED_FLOAT_TO_USHORT(dst[i*4+3], rgba[i][RCOMP]); 1961 CLAMPED_FLOAT_TO_USHORT(dst[i*4+3], rgba[i][RCOMP]);
1921 } 1962 }
1922 break; 1963 break;
1964 case GL_DUDV_ATI:
1965 case GL_DU8DV8_ATI:
1966 for (i=0;i<n;i++) {
1967 dst[i*2+0] = FLOAT_TO_USHORT(rgba[i][RCOMP]);
1968 dst[i*2+1] = FLOAT_TO_USHORT(rgba[i][GCOMP]);
1969 }
1970 break;
1923 default: 1971 default:
1924 _mesa_problem(ctx, "bad format in _mesa_pack_rgba_span\n"); 1972 _mesa_problem(ctx, "bad format in _mesa_pack_rgba_span\n");
1925 } 1973 }
@@ -1993,6 +2041,13 @@ _mesa_pack_rgba_span_float(GLcontext *ctx, GLuint n, GLfloat rgba[][4],
1993 dst[i*4+3] = FLOAT_TO_SHORT(rgba[i][RCOMP]); 2041 dst[i*4+3] = FLOAT_TO_SHORT(rgba[i][RCOMP]);
1994 } 2042 }
1995 break; 2043 break;
2044 case GL_DUDV_ATI:
2045 case GL_DU8DV8_ATI:
2046 for (i=0;i<n;i++) {
2047 dst[i*2+0] = FLOAT_TO_SHORT(rgba[i][RCOMP]);
2048 dst[i*2+1] = FLOAT_TO_SHORT(rgba[i][GCOMP]);
2049 }
2050 break;
1996 default: 2051 default:
1997 _mesa_problem(ctx, "bad format in _mesa_pack_rgba_span\n"); 2052 _mesa_problem(ctx, "bad format in _mesa_pack_rgba_span\n");
1998 } 2053 }
@@ -2066,6 +2121,13 @@ _mesa_pack_rgba_span_float(GLcontext *ctx, GLuint n, GLfloat rgba[][4],
2066 dst[i*4+3] = FLOAT_TO_UINT(rgba[i][RCOMP]); 2121 dst[i*4+3] = FLOAT_TO_UINT(rgba[i][RCOMP]);
2067 } 2122 }
2068 break; 2123 break;
2124 case GL_DUDV_ATI:
2125 case GL_DU8DV8_ATI:
2126 for (i=0;i<n;i++) {
2127 dst[i*2+0] = FLOAT_TO_UINT(rgba[i][RCOMP]);
2128 dst[i*2+1] = FLOAT_TO_UINT(rgba[i][GCOMP]);
2129 }
2130 break;
2069 default: 2131 default:
2070 _mesa_problem(ctx, "bad format in _mesa_pack_rgba_span\n"); 2132 _mesa_problem(ctx, "bad format in _mesa_pack_rgba_span\n");
2071 } 2133 }
@@ -2139,6 +2201,13 @@ _mesa_pack_rgba_span_float(GLcontext *ctx, GLuint n, GLfloat rgba[][4],
2139 dst[i*4+3] = FLOAT_TO_INT(rgba[i][RCOMP]); 2201 dst[i*4+3] = FLOAT_TO_INT(rgba[i][RCOMP]);
2140 } 2202 }
2141 break; 2203 break;
2204 case GL_DUDV_ATI:
2205 case GL_DU8DV8_ATI:
2206 for (i=0;i<n;i++) {
2207 dst[i*2+0] = FLOAT_TO_INT(rgba[i][RCOMP]);
2208 dst[i*2+1] = FLOAT_TO_INT(rgba[i][GCOMP]);
2209 }
2210 break;
2142 default: 2211 default:
2143 _mesa_problem(ctx, "bad format in _mesa_pack_rgba_span\n"); 2212 _mesa_problem(ctx, "bad format in _mesa_pack_rgba_span\n");
2144 } 2213 }
@@ -2212,6 +2281,13 @@ _mesa_pack_rgba_span_float(GLcontext *ctx, GLuint n, GLfloat rgba[][4],
2212 dst[i*4+3] = rgba[i][RCOMP]; 2281 dst[i*4+3] = rgba[i][RCOMP];
2213 } 2282 }
2214 break; 2283 break;
2284 case GL_DUDV_ATI:
2285 case GL_DU8DV8_ATI:
2286 for (i=0;i<n;i++) {
2287 dst[i*2+0] = rgba[i][RCOMP];
2288 dst[i*2+1] = rgba[i][GCOMP];
2289 }
2290 break;
2215 default: 2291 default:
2216 _mesa_problem(ctx, "bad format in _mesa_pack_rgba_span\n"); 2292 _mesa_problem(ctx, "bad format in _mesa_pack_rgba_span\n");
2217 } 2293 }
@@ -2285,6 +2361,13 @@ _mesa_pack_rgba_span_float(GLcontext *ctx, GLuint n, GLfloat rgba[][4],
2285 dst[i*4+3] = _mesa_float_to_half(rgba[i][RCOMP]); 2361 dst[i*4+3] = _mesa_float_to_half(rgba[i][RCOMP]);
2286 } 2362 }
2287 break; 2363 break;
2364 case GL_DUDV_ATI:
2365 case GL_DU8DV8_ATI:
2366 for (i=0;i<n;i++) {
2367 dst[i*2+0] = _mesa_float_to_half(rgba[i][RCOMP]);
2368 dst[i*2+1] = _mesa_float_to_half(rgba[i][GCOMP]);
2369 }
2370 break;
2288 default: 2371 default:
2289 _mesa_problem(ctx, "bad format in _mesa_pack_rgba_span\n"); 2372 _mesa_problem(ctx, "bad format in _mesa_pack_rgba_span\n");
2290 } 2373 }
@@ -2834,7 +2917,8 @@ extract_float_rgba(GLuint n, GLfloat rgba[][4],
2834 srcFormat == GL_BGR || 2917 srcFormat == GL_BGR ||
2835 srcFormat == GL_RGBA || 2918 srcFormat == GL_RGBA ||
2836 srcFormat == GL_BGRA || 2919 srcFormat == GL_BGRA ||
2837 srcFormat == GL_ABGR_EXT); 2920 srcFormat == GL_ABGR_EXT ||
2921 srcFormat == GL_DUDV_ATI);
2838 2922
2839 ASSERT(srcType == GL_UNSIGNED_BYTE || 2923 ASSERT(srcType == GL_UNSIGNED_BYTE ||
2840 srcType == GL_BYTE || 2924 srcType == GL_BYTE ||
@@ -2949,6 +3033,13 @@ extract_float_rgba(GLuint n, GLfloat rgba[][4],
2949 aComp = 0; 3033 aComp = 0;
2950 stride = 4; 3034 stride = 4;
2951 break; 3035 break;
3036 case GL_DUDV_ATI:
3037 redIndex = 0;
3038 greenIndex = 1;
3039 blueIndex = -1;
3040 alphaIndex = -1;
3041 stride = 2;
3042 break;
2952 default: 3043 default:
2953 _mesa_problem(NULL, "bad srcFormat in extract float data"); 3044 _mesa_problem(NULL, "bad srcFormat in extract float data");
2954 return; 3045 return;
@@ -3877,6 +3968,62 @@ _mesa_unpack_color_span_float( GLcontext *ctx,
3877 } 3968 }
3878} 3969}
3879 3970
3971/**
3972 * Similar to _mesa_unpack_color_span_float(), but for dudv data instead of rgba,
3973 * directly return GLbyte data, no transfer ops apply.
3974 */
3975void
3976_mesa_unpack_dudv_span_byte( GLcontext *ctx,
3977 GLuint n, GLenum dstFormat, GLbyte dest[],
3978 GLenum srcFormat, GLenum srcType,
3979 const GLvoid *source,
3980 const struct gl_pixelstore_attrib *srcPacking,
3981 GLbitfield transferOps )
3982{
3983 ASSERT(dstFormat == GL_DUDV_ATI);
3984 ASSERT(srcFormat == GL_DUDV_ATI);
3985
3986 ASSERT(srcType == GL_UNSIGNED_BYTE ||
3987 srcType == GL_BYTE ||
3988 srcType == GL_UNSIGNED_SHORT ||
3989 srcType == GL_SHORT ||
3990 srcType == GL_UNSIGNED_INT ||
3991 srcType == GL_INT ||
3992 srcType == GL_HALF_FLOAT_ARB ||
3993 srcType == GL_FLOAT);
3994
3995 /* general solution */
3996 {
3997 GLint dstComponents;
3998 GLfloat rgba[MAX_WIDTH][4];
3999
4000 dstComponents = _mesa_components_in_format( dstFormat );
4001 /* source & dest image formats should have been error checked by now */
4002 assert(dstComponents > 0);
4003
4004 /*
4005 * Extract image data and convert to RGBA floats
4006 */
4007 assert(n <= MAX_WIDTH);
4008 extract_float_rgba(n, rgba, srcFormat, srcType, source,
4009 srcPacking->SwapBytes);
4010
4011
4012 /* Now determine which color channels we need to produce.
4013 * And determine the dest index (offset) within each color tuple.
4014 */
4015
4016 /* Now pack results in the requested dstFormat */
4017 GLbyte *dst = dest;
4018 GLuint i;
4019 for (i = 0; i < n; i++) {
4020 /* not sure - need clamp[-1,1] here? */
4021 dst[0] = FLOAT_TO_BYTE(rgba[i][RCOMP]);
4022 dst[1] = FLOAT_TO_BYTE(rgba[i][GCOMP]);
4023 dst += dstComponents;
4024 }
4025 }
4026}
3880 4027
3881/* 4028/*
3882 * Unpack a row of color index data from a client buffer according to 4029 * Unpack a row of color index data from a client buffer according to
diff --git a/src/mesa/main/image.h b/src/mesa/main/image.h
index 0e0bbd96d85..b26c27e5a8a 100644
--- a/src/mesa/main/image.h
+++ b/src/mesa/main/image.h
@@ -198,6 +198,13 @@ _mesa_unpack_color_span_float( GLcontext *ctx,
198 const struct gl_pixelstore_attrib *srcPacking, 198 const struct gl_pixelstore_attrib *srcPacking,
199 GLbitfield transferOps ); 199 GLbitfield transferOps );
200 200
201extern void
202_mesa_unpack_dudv_span_byte( GLcontext *ctx,
203 GLuint n, GLenum dstFormat, GLbyte dest[],
204 GLenum srcFormat, GLenum srcType,
205 const GLvoid *source,
206 const struct gl_pixelstore_attrib *srcPacking,
207 GLbitfield transferOps );
201 208
202extern void 209extern void
203_mesa_unpack_index_span( const GLcontext *ctx, GLuint n, 210_mesa_unpack_index_span( const GLcontext *ctx, GLuint n,
diff --git a/src/mesa/main/macros.h b/src/mesa/main/macros.h
index 2630855a0ea..bfd740870ec 100644
--- a/src/mesa/main/macros.h
+++ b/src/mesa/main/macros.h
@@ -54,13 +54,16 @@ extern GLfloat _mesa_ubyte_to_float_color_tab[256];
54#define FLOAT_TO_BYTE(X) ( (((GLint) (255.0F * (X))) - 1) / 2 ) 54#define FLOAT_TO_BYTE(X) ( (((GLint) (255.0F * (X))) - 1) / 2 )
55 55
56 56
57/** Convert GLushort in [0,65536] to GLfloat in [0.0,1.0] */ 57/** Convert GLushort in [0,65535] to GLfloat in [0.0,1.0] */
58#define USHORT_TO_FLOAT(S) ((GLfloat) (S) * (1.0F / 65535.0F)) 58#define USHORT_TO_FLOAT(S) ((GLfloat) (S) * (1.0F / 65535.0F))
59 59
60/** Convert GLfloat in [0.0,1.0] to GLushort in [0, 65535] */
61#define FLOAT_TO_USHORT(X) ((GLuint) ((X) * 65535.0))
62
60/** Convert GLshort in [-32768,32767] to GLfloat in [-1.0,1.0] */ 63/** Convert GLshort in [-32768,32767] to GLfloat in [-1.0,1.0] */
61#define SHORT_TO_FLOAT(S) ((2.0F * (S) + 1.0F) * (1.0F/65535.0F)) 64#define SHORT_TO_FLOAT(S) ((2.0F * (S) + 1.0F) * (1.0F/65535.0F))
62 65
63/** Convert GLfloat in [0.0,1.0] to GLshort in [-32768,32767] */ 66/** Convert GLfloat in [-1.0,1.0] to GLshort in [-32768,32767] */
64#define FLOAT_TO_SHORT(X) ( (((GLint) (65535.0F * (X))) - 1) / 2 ) 67#define FLOAT_TO_SHORT(X) ( (((GLint) (65535.0F * (X))) - 1) / 2 )
65 68
66 69
diff --git a/src/mesa/main/mipmap.c b/src/mesa/main/mipmap.c
index 3dd4b3391b9..af2bf8fe228 100644
--- a/src/mesa/main/mipmap.c
+++ b/src/mesa/main/mipmap.c
@@ -85,7 +85,7 @@ bytes_per_pixel(GLenum datatype, GLuint comps)
85 rowC[j][e], rowC[k][e], \ 85 rowC[j][e], rowC[k][e], \
86 rowD[j][e], rowD[k][e]); \ 86 rowD[j][e], rowD[k][e]); \
87 } while(0) 87 } while(0)
88 88
89#define FILTER_F_3D(e) \ 89#define FILTER_F_3D(e) \
90 do { \ 90 do { \
91 dst[i][e] = (rowA[j][e] + rowA[k][e] \ 91 dst[i][e] = (rowA[j][e] + rowA[k][e] \
@@ -226,7 +226,6 @@ do_row(GLenum datatype, GLuint comps, GLint srcWidth,
226 dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) / 4; 226 dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) / 4;
227 } 227 }
228 } 228 }
229
230 else if (datatype == GL_FLOAT && comps == 4) { 229 else if (datatype == GL_FLOAT && comps == 4) {
231 GLuint i, j, k; 230 GLuint i, j, k;
232 const GLfloat(*rowA)[4] = (const GLfloat(*)[4]) srcRowA; 231 const GLfloat(*rowA)[4] = (const GLfloat(*)[4]) srcRowA;
@@ -471,6 +470,17 @@ do_row(GLenum datatype, GLuint comps, GLint srcWidth,
471 dst[i] = (blue << 5) | (green << 2) | red; 470 dst[i] = (blue << 5) | (green << 2) | red;
472 } 471 }
473 } 472 }
473 else if (datatype == GL_BYTE && comps == 2) {
474 GLuint i, j, k;
475 const GLbyte(*rowA)[2] = (const GLbyte(*)[2]) srcRowA;
476 const GLbyte(*rowB)[2] = (const GLbyte(*)[2]) srcRowB;
477 GLbyte(*dst)[2] = (GLbyte(*)[2]) dstRow;
478 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
479 i++, j += colStride, k += colStride) {
480 dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) >> 2;
481 dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) >> 2;
482 }
483 }
474 else { 484 else {
475 _mesa_problem(NULL, "bad format in do_row()"); 485 _mesa_problem(NULL, "bad format in do_row()");
476 } 486 }
diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h
index 9080c83da4e..169f1af057d 100644
--- a/src/mesa/main/mtypes.h
+++ b/src/mesa/main/mtypes.h
@@ -1390,6 +1390,8 @@ struct gl_texture_unit
1390 GLbitfield _GenFlags; /**< Bitwise-OR of Gen[STRQ]._ModeBit */ 1390 GLbitfield _GenFlags; /**< Bitwise-OR of Gen[STRQ]._ModeBit */
1391 1391
1392 GLfloat LodBias; /**< for biasing mipmap levels */ 1392 GLfloat LodBias; /**< for biasing mipmap levels */
1393 GLenum BumpTarget;
1394 GLfloat RotMatrix[4]; /* 2x2 matrix */
1393 1395
1394 /** 1396 /**
1395 * \name GL_EXT_texture_env_combine 1397 * \name GL_EXT_texture_env_combine
@@ -2388,6 +2390,8 @@ struct gl_constants
2388 GLuint MaxSamples; /**< GL_ARB_framebuffer_object */ 2390 GLuint MaxSamples; /**< GL_ARB_framebuffer_object */
2389 2391
2390 GLuint MaxVarying; /**< Number of float[4] varying parameters */ 2392 GLuint MaxVarying; /**< Number of float[4] varying parameters */
2393
2394 GLbitfield SupportedBumpUnits; /**> units supporting GL_ATI_envmap_bumpmap as targets */
2391}; 2395};
2392 2396
2393 2397
@@ -2484,6 +2488,7 @@ struct gl_extensions
2484 GLboolean APPLE_client_storage; 2488 GLboolean APPLE_client_storage;
2485 GLboolean APPLE_packed_pixels; 2489 GLboolean APPLE_packed_pixels;
2486 GLboolean APPLE_vertex_array_object; 2490 GLboolean APPLE_vertex_array_object;
2491 GLboolean ATI_envmap_bumpmap;
2487 GLboolean ATI_texture_mirror_once; 2492 GLboolean ATI_texture_mirror_once;
2488 GLboolean ATI_texture_env_combine3; 2493 GLboolean ATI_texture_env_combine3;
2489 GLboolean ATI_fragment_shader; 2494 GLboolean ATI_fragment_shader;
diff --git a/src/mesa/main/texenv.c b/src/mesa/main/texenv.c
index 95547a500ee..c2960fc8208 100644
--- a/src/mesa/main/texenv.c
+++ b/src/mesa/main/texenv.c
@@ -142,7 +142,11 @@ set_combiner_mode(GLcontext *ctx,
142 case GL_MODULATE_ADD_ATI: 142 case GL_MODULATE_ADD_ATI:
143 case GL_MODULATE_SIGNED_ADD_ATI: 143 case GL_MODULATE_SIGNED_ADD_ATI:
144 case GL_MODULATE_SUBTRACT_ATI: 144 case GL_MODULATE_SUBTRACT_ATI:
145 legal =ctx->Extensions.ATI_texture_env_combine3; 145 legal = ctx->Extensions.ATI_texture_env_combine3;
146 break;
147 case GL_BUMP_ENVMAP_ATI:
148 legal = (ctx->Extensions.ATI_envmap_bumpmap &&
149 pname == GL_COMBINE_RGB);
146 break; 150 break;
147 default: 151 default:
148 legal = GL_FALSE; 152 legal = GL_FALSE;
@@ -500,6 +504,26 @@ _mesa_TexEnvfv( GLenum target, GLenum pname, const GLfloat *param )
500 case GL_ALPHA_SCALE: 504 case GL_ALPHA_SCALE:
501 set_combiner_scale(ctx, texUnit, pname, param[0]); 505 set_combiner_scale(ctx, texUnit, pname, param[0]);
502 break; 506 break;
507 case GL_BUMP_TARGET_ATI:
508 if (!ctx->Extensions.ATI_envmap_bumpmap) {
509 _mesa_error( ctx, GL_INVALID_ENUM, "glTexEnv(pname=0x%x)", pname );
510 return;
511 }
512 if (((GLenum) (GLint) param[0] < GL_TEXTURE0) ||
513 ((GLenum) (GLint) param[0] > GL_TEXTURE31)) {
514 /* spec doesn't say this but it seems logical */
515 _mesa_error( ctx, GL_INVALID_ENUM, "glTexEnv(param=0x%x)", (GLenum) (GLint) param[0]);
516 return;
517 }
518 if (!((1 << ((GLenum) (GLint) param[0] - GL_TEXTURE0)) & ctx->Const.SupportedBumpUnits)) {
519 _mesa_error( ctx, GL_INVALID_VALUE, "glTexEnv(param=0x%x)", (GLenum) (GLint) param[0]);
520 return;
521 }
522 else {
523 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
524 texUnit->BumpTarget = (GLenum) (GLint) param[0];
525 }
526 break;
503 default: 527 default:
504 _mesa_error( ctx, GL_INVALID_ENUM, "glTexEnv(pname)" ); 528 _mesa_error( ctx, GL_INVALID_ENUM, "glTexEnv(pname)" );
505 return; 529 return;
@@ -735,6 +759,16 @@ get_texenvi(GLcontext *ctx, const struct gl_texture_unit *texUnit,
735 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)"); 759 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
736 } 760 }
737 break; 761 break;
762 case GL_BUMP_TARGET_ATI:
763 /* spec doesn't say so, but I think this should be queryable */
764 if (ctx->Extensions.ATI_envmap_bumpmap) {
765 return texUnit->BumpTarget;
766 }
767 else {
768 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
769 }
770 break;
771
738 default: 772 default:
739 ; 773 ;
740 } 774 }
@@ -874,4 +908,142 @@ _mesa_GetTexEnviv( GLenum target, GLenum pname, GLint *params )
874 } 908 }
875} 909}
876 910
911/* why does ATI_envmap_bumpmap require new entrypoints? Should just
912 reuse TexEnv ones... */
913void GLAPIENTRY
914_mesa_TexBumpParameterivATI( GLenum pname, const GLint *param )
915{
916 GLfloat p[4];
917 if (pname == GL_BUMP_ROT_MATRIX_ATI) {
918 /* hope that conversion is correct here */
919 p[0] = INT_TO_FLOAT( param[0] );
920 p[1] = INT_TO_FLOAT( param[1] );
921 p[2] = INT_TO_FLOAT( param[2] );
922 p[3] = INT_TO_FLOAT( param[3] );
923 }
924 else {
925 p[0] = (GLfloat) param[0];
926 p[1] = p[2] = p[3] = 0; /* init to zero, just to be safe */
927 }
928 _mesa_TexBumpParameterfvATI( pname, p );
929}
930
931void GLAPIENTRY
932_mesa_TexBumpParameterfvATI( GLenum pname, const GLfloat *param )
933{
934 struct gl_texture_unit *texUnit;
935 GET_CURRENT_CONTEXT(ctx);
936 ASSERT_OUTSIDE_BEGIN_END(ctx);
937
938 /* should return error if extension not supported? */
939 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
940
941 if (pname == GL_BUMP_ROT_MATRIX_ATI) {
942 if (TEST_EQ_4V(param, texUnit->RotMatrix))
943 return;
944 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
945 COPY_4FV(texUnit->RotMatrix, param);
946 }
947 else {
948 _mesa_error( ctx, GL_INVALID_ENUM, "glTexBumpParameter(pname)" );
949 return;
950 }
951 /* Drivers might want to know about this, instead of dedicated function
952 just shove it into TexEnv where it really belongs anyway */
953 if (ctx->Driver.TexEnv) {
954 (*ctx->Driver.TexEnv)( ctx, 0, pname, param );
955 }
956}
957
958void GLAPIENTRY
959_mesa_GetTexBumpParameterivATI( GLenum pname, GLint *param )
960{
961 const struct gl_texture_unit *texUnit;
962 GLint i;
963 GLint temp = 0;
964 GET_CURRENT_CONTEXT(ctx);
965 ASSERT_OUTSIDE_BEGIN_END(ctx);
966
967 /* should return error if extension not supported? */
968 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
969
970 if (pname == GL_BUMP_ROT_MATRIX_SIZE_ATI) {
971 /* spec leaves open to support larger matrices.
972 Don't think anyone would ever want to use it
973 (and apps almost certainly would not understand it and
974 thus fail to submit matrices correctly) so hardcode this. */
975 *param = 4;
976 }
977 else if (pname == GL_BUMP_ROT_MATRIX_ATI) {
978 /* hope that conversion is correct here */
979 param[0] = FLOAT_TO_INT(texUnit->RotMatrix[0]);
980 param[1] = FLOAT_TO_INT(texUnit->RotMatrix[1]);
981 param[2] = FLOAT_TO_INT(texUnit->RotMatrix[2]);
982 param[3] = FLOAT_TO_INT(texUnit->RotMatrix[3]);
983 }
984 else if (pname == GL_BUMP_NUM_TEX_UNITS_ATI) {
985 for (i = 0; i < ctx->Const.MaxTextureImageUnits; i++) {
986 if (ctx->Const.SupportedBumpUnits & (1 << i)) {
987 temp++;
988 }
989 }
990 *param = temp;
991 }
992 else if (pname == GL_BUMP_TEX_UNITS_ATI) {
993 for (i = 0; i < ctx->Const.MaxTextureImageUnits; i++) {
994 if (ctx->Const.SupportedBumpUnits & (1 << i)) {
995 *param++ = i + GL_TEXTURE0;
996 }
997 }
998 }
999 else {
1000 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexBumpParameter(pname)" );
1001 return;
1002 }
1003}
1004
1005void GLAPIENTRY
1006_mesa_GetTexBumpParameterfvATI( GLenum pname, GLfloat *param )
1007{
1008 const struct gl_texture_unit *texUnit;
1009 GLint i;
1010 GLint temp = 0;
1011 GET_CURRENT_CONTEXT(ctx);
1012 ASSERT_OUTSIDE_BEGIN_END(ctx);
1013
1014 /* should return error if extension not supported? */
1015 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1016
1017 if (pname == GL_BUMP_ROT_MATRIX_SIZE_ATI) {
1018 /* spec leaves open to support larger matrices.
1019 Don't think anyone would ever want to use it
1020 (and apps might not understand it) so hardcode this. */
1021 *param = (GLfloat) 4;
1022 }
1023 else if (pname == GL_BUMP_ROT_MATRIX_ATI) {
1024 param[0] = texUnit->RotMatrix[0];
1025 param[1] = texUnit->RotMatrix[1];
1026 param[2] = texUnit->RotMatrix[2];
1027 param[3] = texUnit->RotMatrix[3];
1028 }
1029 else if (pname == GL_BUMP_NUM_TEX_UNITS_ATI) {
1030 for (i = 0; i < ctx->Const.MaxTextureImageUnits; i++) {
1031 if (ctx->Const.SupportedBumpUnits & (1 << i)) {
1032 temp++;
1033 }
1034 }
1035 *param = (GLfloat) temp;
1036 }
1037 else if (pname == GL_BUMP_TEX_UNITS_ATI) {
1038 for (i = 0; i < ctx->Const.MaxTextureImageUnits; i++) {
1039 if (ctx->Const.SupportedBumpUnits & (1 << i)) {
1040 *param++ = (GLfloat) (i + GL_TEXTURE0);
1041 }
1042 }
1043 }
1044 else {
1045 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexBumpParameter(pname)" );
1046 return;
1047 }
1048}
877 1049
diff --git a/src/mesa/main/texenv.h b/src/mesa/main/texenv.h
index bdff7fdb82b..1e9c5faed79 100644
--- a/src/mesa/main/texenv.h
+++ b/src/mesa/main/texenv.h
@@ -48,5 +48,16 @@ _mesa_TexEnvi( GLenum target, GLenum pname, GLint param );
48extern void GLAPIENTRY 48extern void GLAPIENTRY
49_mesa_TexEnviv( GLenum target, GLenum pname, const GLint *param ); 49_mesa_TexEnviv( GLenum target, GLenum pname, const GLint *param );
50 50
51extern void GLAPIENTRY
52_mesa_TexBumpParameterivATI( GLenum pname, const GLint *param );
53
54extern void GLAPIENTRY
55_mesa_TexBumpParameterfvATI( GLenum pname, const GLfloat *param );
56
57extern void GLAPIENTRY
58_mesa_GetTexBumpParameterivATI( GLenum pname, GLint *param );
59
60extern void GLAPIENTRY
61_mesa_GetTexBumpParameterfvATI( GLenum pname, GLfloat *param );
51 62
52#endif /* TEXENV_H */ 63#endif /* TEXENV_H */
diff --git a/src/mesa/main/texenvprogram.c b/src/mesa/main/texenvprogram.c
index 51c13a563d6..3fbd119b347 100644
--- a/src/mesa/main/texenvprogram.c
+++ b/src/mesa/main/texenvprogram.c
@@ -94,11 +94,11 @@ struct state_key {
94 GLuint ScaleShiftA:2; 94 GLuint ScaleShiftA:2;
95 95
96 GLuint NumArgsRGB:3; 96 GLuint NumArgsRGB:3;
97 GLuint ModeRGB:4; 97 GLuint ModeRGB:5;
98 struct mode_opt OptRGB[MAX_TERMS]; 98 struct mode_opt OptRGB[MAX_TERMS];
99 99
100 GLuint NumArgsA:3; 100 GLuint NumArgsA:3;
101 GLuint ModeA:4; 101 GLuint ModeA:5;
102 struct mode_opt OptA[MAX_TERMS]; 102 struct mode_opt OptA[MAX_TERMS];
103 } unit[8]; 103 } unit[8];
104}; 104};
@@ -194,7 +194,8 @@ static GLuint translate_source( GLenum src )
194#define MODE_MODULATE_SUBTRACT_ATI 12 /* r = a0 * a2 - a1 */ 194#define MODE_MODULATE_SUBTRACT_ATI 12 /* r = a0 * a2 - a1 */
195#define MODE_ADD_PRODUCTS 13 /* r = a0 * a1 + a2 * a3 */ 195#define MODE_ADD_PRODUCTS 13 /* r = a0 * a1 + a2 * a3 */
196#define MODE_ADD_PRODUCTS_SIGNED 14 /* r = a0 * a1 + a2 * a3 - 0.5 */ 196#define MODE_ADD_PRODUCTS_SIGNED 14 /* r = a0 * a1 + a2 * a3 - 0.5 */
197#define MODE_UNKNOWN 15 197#define MODE_BUMP_ENVMAP_ATI 15 /* special */
198#define MODE_UNKNOWN 16
198 199
199/** 200/**
200 * Translate GL combiner state into a MODE_x value 201 * Translate GL combiner state into a MODE_x value
@@ -223,6 +224,7 @@ static GLuint translate_mode( GLenum envMode, GLenum mode )
223 case GL_MODULATE_ADD_ATI: return MODE_MODULATE_ADD_ATI; 224 case GL_MODULATE_ADD_ATI: return MODE_MODULATE_ADD_ATI;
224 case GL_MODULATE_SIGNED_ADD_ATI: return MODE_MODULATE_SIGNED_ADD_ATI; 225 case GL_MODULATE_SIGNED_ADD_ATI: return MODE_MODULATE_SIGNED_ADD_ATI;
225 case GL_MODULATE_SUBTRACT_ATI: return MODE_MODULATE_SUBTRACT_ATI; 226 case GL_MODULATE_SUBTRACT_ATI: return MODE_MODULATE_SUBTRACT_ATI;
227 case GL_BUMP_ENVMAP_ATI: return MODE_BUMP_ENVMAP_ATI;
226 default: 228 default:
227 assert(0); 229 assert(0);
228 return MODE_UNKNOWN; 230 return MODE_UNKNOWN;
@@ -383,7 +385,7 @@ static void make_state_key( GLcontext *ctx, struct state_key *key )
383 translate_mode(texUnit->EnvMode, texUnit->_CurrentCombine->ModeRGB); 385 translate_mode(texUnit->EnvMode, texUnit->_CurrentCombine->ModeRGB);
384 key->unit[i].ModeA = 386 key->unit[i].ModeA =
385 translate_mode(texUnit->EnvMode, texUnit->_CurrentCombine->ModeA); 387 translate_mode(texUnit->EnvMode, texUnit->_CurrentCombine->ModeA);
386 388
387 key->unit[i].ScaleShiftRGB = texUnit->_CurrentCombine->ScaleShiftRGB; 389 key->unit[i].ScaleShiftRGB = texUnit->_CurrentCombine->ScaleShiftRGB;
388 key->unit[i].ScaleShiftA = texUnit->_CurrentCombine->ScaleShiftA; 390 key->unit[i].ScaleShiftA = texUnit->_CurrentCombine->ScaleShiftA;
389 391
@@ -397,8 +399,18 @@ static void make_state_key( GLcontext *ctx, struct state_key *key )
397 key->unit[i].OptA[j].Source = 399 key->unit[i].OptA[j].Source =
398 translate_source(texUnit->_CurrentCombine->SourceA[j]); 400 translate_source(texUnit->_CurrentCombine->SourceA[j]);
399 } 401 }
402
403 if (key->unit[i].ModeRGB == MODE_BUMP_ENVMAP_ATI) {
404 /* requires some special translation */
405 key->unit[i].NumArgsRGB = 2;
406 key->unit[i].ScaleShiftRGB = 0;
407 key->unit[i].OptRGB[0].Operand = OPR_SRC_COLOR;
408 key->unit[i].OptRGB[0].Source = SRC_TEXTURE;
409 key->unit[i].OptRGB[1].Operand = OPR_SRC_COLOR;
410 key->unit[i].OptRGB[1].Source = texUnit->BumpTarget - GL_TEXTURE0 + SRC_TEXTURE0;
411 }
400 } 412 }
401 413
402 if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) { 414 if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) {
403 key->separate_specular = 1; 415 key->separate_specular = 1;
404 inputs_referenced |= FRAG_BIT_COL1; 416 inputs_referenced |= FRAG_BIT_COL1;
@@ -464,6 +476,11 @@ struct texenv_fragment_program {
464 * else undef. 476 * else undef.
465 */ 477 */
466 478
479 struct ureg texcoord_tex[MAX_TEXTURE_COORD_UNITS];
480 /* Reg containing texcoord for a texture unit,
481 * needed for bump mapping, else undef.
482 */
483
467 struct ureg src_previous; /**< Reg containing color from previous 484 struct ureg src_previous; /**< Reg containing color from previous
468 * stage. May need to be decl'd. 485 * stage. May need to be decl'd.
469 */ 486 */
@@ -756,6 +773,7 @@ static struct ureg emit_texld( struct texenv_fragment_program *p,
756 */ 773 */
757 reserve_temp(p, dest); 774 reserve_temp(p, dest);
758 775
776#if 0
759 /* Is this a texture indirection? 777 /* Is this a texture indirection?
760 */ 778 */
761 if ((coord.file == PROGRAM_TEMPORARY && 779 if ((coord.file == PROGRAM_TEMPORARY &&
@@ -767,6 +785,7 @@ static struct ureg emit_texld( struct texenv_fragment_program *p,
767 p->alu_temps = 0; 785 p->alu_temps = 0;
768 assert(0); /* KW: texture env crossbar */ 786 assert(0); /* KW: texture env crossbar */
769 } 787 }
788#endif
770 789
771 return dest; 790 return dest;
772} 791}
@@ -1052,6 +1071,10 @@ static struct ureg emit_combine( struct texenv_fragment_program *p,
1052 emit_arith( p, OPCODE_SUB, dest, mask, saturate, tmp0, half, undef ); 1071 emit_arith( p, OPCODE_SUB, dest, mask, saturate, tmp0, half, undef );
1053 } 1072 }
1054 return dest; 1073 return dest;
1074 case MODE_BUMP_ENVMAP_ATI:
1075 /* special - not handled here */
1076 assert(0);
1077 return src[0];
1055 default: 1078 default:
1056 assert(0); 1079 assert(0);
1057 return src[0]; 1080 return src[0];
@@ -1074,6 +1097,10 @@ emit_texenv(struct texenv_fragment_program *p, GLuint unit)
1074 if (!key->unit[unit].enabled) { 1097 if (!key->unit[unit].enabled) {
1075 return get_source(p, SRC_PREVIOUS, 0); 1098 return get_source(p, SRC_PREVIOUS, 0);
1076 } 1099 }
1100 if (key->unit[unit].ModeRGB == MODE_BUMP_ENVMAP_ATI) {
1101 /* this isn't really a env stage delivering a color and handled elsewhere */
1102 return get_source(p, SRC_PREVIOUS, 0);
1103 }
1077 1104
1078 switch (key->unit[unit].ModeRGB) { 1105 switch (key->unit[unit].ModeRGB) {
1079 case MODE_DOT3_RGB_EXT: 1106 case MODE_DOT3_RGB_EXT:
@@ -1163,9 +1190,17 @@ static void load_texture( struct texenv_fragment_program *p, GLuint unit )
1163{ 1190{
1164 if (is_undef(p->src_texture[unit])) { 1191 if (is_undef(p->src_texture[unit])) {
1165 GLuint texTarget = p->state->unit[unit].source_index; 1192 GLuint texTarget = p->state->unit[unit].source_index;
1166 struct ureg texcoord = register_input(p, FRAG_ATTRIB_TEX0+unit); 1193 struct ureg texcoord;
1167 struct ureg tmp = get_tex_temp( p ); 1194 struct ureg tmp = get_tex_temp( p );
1168 1195
1196 if (is_undef(p->texcoord_tex[unit])) {
1197 texcoord = register_input(p, FRAG_ATTRIB_TEX0+unit);
1198 }
1199 else {
1200 /* might want to reuse this reg for tex output actually */
1201 texcoord = p->texcoord_tex[unit];
1202 }
1203
1169 if (texTarget == TEXTURE_UNKNOWN_INDEX) 1204 if (texTarget == TEXTURE_UNKNOWN_INDEX)
1170 program_error(p, "TexSrcBit"); 1205 program_error(p, "TexSrcBit");
1171 1206
@@ -1233,7 +1268,7 @@ load_texunit_sources( struct texenv_fragment_program *p, int unit )
1233 GLuint i; 1268 GLuint i;
1234 1269
1235 for (i = 0; i < key->unit[unit].NumArgsRGB; i++) { 1270 for (i = 0; i < key->unit[unit].NumArgsRGB; i++) {
1236 load_texenv_source( p, key->unit[unit].OptRGB[i].Source, unit); 1271 load_texenv_source( p, key->unit[unit].OptRGB[i].Source, unit );
1237 } 1272 }
1238 1273
1239 for (i = 0; i < key->unit[unit].NumArgsA; i++) { 1274 for (i = 0; i < key->unit[unit].NumArgsA; i++) {
@@ -1243,6 +1278,40 @@ load_texunit_sources( struct texenv_fragment_program *p, int unit )
1243 return GL_TRUE; 1278 return GL_TRUE;
1244} 1279}
1245 1280
1281/**
1282 * Generate instructions for loading bump map textures.
1283 */
1284static GLboolean
1285load_texunit_bumpmap( struct texenv_fragment_program *p, int unit )
1286{
1287 struct state_key *key = p->state;
1288 GLuint bumpedUnitNr = key->unit[unit].OptRGB[1].Source - SRC_TEXTURE0;
1289 struct ureg texcDst, bumpMapRes;
1290 struct ureg constdudvcolor = register_const4f(p, 0.0, 0.0, 0.0, 1.0);
1291 struct ureg texcSrc = register_input(p, FRAG_ATTRIB_TEX0 + bumpedUnitNr);
1292 struct ureg rotMat0 = register_param3( p, STATE_INTERNAL, STATE_ROT_MATRIX_0, unit );
1293 struct ureg rotMat1 = register_param3( p, STATE_INTERNAL, STATE_ROT_MATRIX_1, unit );
1294
1295 load_texenv_source( p, unit + SRC_TEXTURE0, unit );
1296
1297 bumpMapRes = get_source(p, key->unit[unit].OptRGB[0].Source, unit);
1298 texcDst = get_tex_temp( p );
1299 p->texcoord_tex[bumpedUnitNr] = texcDst;
1300
1301 /* apply rot matrix and add coords to be available in next phase */
1302 /* dest = (Arg0.xxxx * rotMat0 + Arg1) + (Arg0.yyyy * rotMat1) */
1303 /* note only 2 coords are affected the rest are left unchanged (mul by 0) */
1304 emit_arith( p, OPCODE_MAD, texcDst, WRITEMASK_XYZW, 0,
1305 swizzle1(bumpMapRes, SWIZZLE_X), rotMat0, texcSrc );
1306 emit_arith( p, OPCODE_MAD, texcDst, WRITEMASK_XYZW, 0,
1307 swizzle1(bumpMapRes, SWIZZLE_Y), rotMat1, texcDst );
1308
1309 /* move 0,0,0,1 into bumpmap src if someone (crossbar) is foolish
1310 enough to access this later, should optimize away */
1311 emit_arith( p, OPCODE_MOV, bumpMapRes, WRITEMASK_XYZW, 0, constdudvcolor, undef, undef );
1312
1313 return GL_TRUE;
1314}
1246 1315
1247/** 1316/**
1248 * Generate a new fragment program which implements the context's 1317 * Generate a new fragment program which implements the context's
@@ -1267,7 +1336,7 @@ create_new_program(GLcontext *ctx, struct state_key *key,
1267 */ 1336 */
1268 p.program->Base.Instructions = instBuffer; 1337 p.program->Base.Instructions = instBuffer;
1269 p.program->Base.Target = GL_FRAGMENT_PROGRAM_ARB; 1338 p.program->Base.Target = GL_FRAGMENT_PROGRAM_ARB;
1270 p.program->Base.NumTexIndirections = 1; /* correct? */ 1339 p.program->Base.NumTexIndirections = 1;
1271 p.program->Base.NumTexInstructions = 0; 1340 p.program->Base.NumTexInstructions = 0;
1272 p.program->Base.NumAluInstructions = 0; 1341 p.program->Base.NumAluInstructions = 0;
1273 p.program->Base.String = NULL; 1342 p.program->Base.String = NULL;
@@ -1280,8 +1349,10 @@ create_new_program(GLcontext *ctx, struct state_key *key,
1280 p.program->Base.InputsRead = 0; 1349 p.program->Base.InputsRead = 0;
1281 p.program->Base.OutputsWritten = 1 << FRAG_RESULT_COLOR; 1350 p.program->Base.OutputsWritten = 1 << FRAG_RESULT_COLOR;
1282 1351
1283 for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) 1352 for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
1284 p.src_texture[unit] = undef; 1353 p.src_texture[unit] = undef;
1354 p.texcoord_tex[unit] = undef;
1355 }
1285 1356
1286 p.src_previous = undef; 1357 p.src_previous = undef;
1287 p.half = undef; 1358 p.half = undef;
@@ -1292,6 +1363,16 @@ create_new_program(GLcontext *ctx, struct state_key *key,
1292 release_temps(ctx, &p); 1363 release_temps(ctx, &p);
1293 1364
1294 if (key->enabled_units) { 1365 if (key->enabled_units) {
1366 GLboolean needbumpstage = GL_FALSE;
1367 /* Zeroth pass - bump map textures first */
1368 for (unit = 0 ; unit < ctx->Const.MaxTextureUnits ; unit++)
1369 if (key->unit[unit].enabled && key->unit[unit].ModeRGB == MODE_BUMP_ENVMAP_ATI) {
1370 needbumpstage = GL_TRUE;
1371 load_texunit_bumpmap( &p, unit );
1372 }
1373 if (needbumpstage)
1374 p.program->Base.NumTexIndirections++;
1375
1295 /* First pass - to support texture_env_crossbar, first identify 1376 /* First pass - to support texture_env_crossbar, first identify
1296 * all referenced texture sources and emit texld instructions 1377 * all referenced texture sources and emit texld instructions
1297 * for each: 1378 * for each:
diff --git a/src/mesa/main/texformat.c b/src/mesa/main/texformat.c
index 16d05cc7d07..61a12493a6b 100644
--- a/src/mesa/main/texformat.c
+++ b/src/mesa/main/texformat.c
@@ -696,6 +696,33 @@ const struct gl_texture_format _mesa_texformat_intensity_float16 = {
696 store_texel_intensity_f16 /* StoreTexel */ 696 store_texel_intensity_f16 /* StoreTexel */
697}; 697};
698 698
699const struct gl_texture_format _mesa_texformat_dudv8 = {
700 MESA_FORMAT_DUDV8, /* MesaFormat */
701 GL_DUDV_ATI, /* BaseFormat */
702 /* FIXME: spec doesn't say since that parameter didn't exist then,
703 but this should be something like SIGNED_NORMALIZED */
704 GL_UNSIGNED_NORMALIZED_ARB, /* DataType */
705 /* maybe should add dudvBits field, but spec seems to be
706 lacking the ability to query with GetTexLevelParameter anyway */
707 0, /* RedBits */
708 0, /* GreenBits */
709 0, /* BlueBits */
710 0, /* AlphaBits */
711 0, /* LuminanceBits */
712 0, /* IntensityBits */
713 0, /* IndexBits */
714 0, /* DepthBits */
715 0, /* StencilBits */
716 2, /* TexelBytes */
717 _mesa_texstore_dudv8, /* StoreTexImageFunc */
718 NULL, /* FetchTexel1D */
719 NULL, /* FetchTexel2D */
720 NULL, /* FetchTexel3D */
721 NULL, /* FetchTexel1Df */
722 fetch_texel_2d_dudv8, /* FetchTexel2Df */
723 NULL, /* FetchTexel3Df */
724 NULL /* StoreTexel */
725};
699 726
700/*@}*/ 727/*@}*/
701 728
@@ -1634,6 +1661,16 @@ _mesa_choose_tex_format( GLcontext *ctx, GLint internalFormat,
1634 } 1661 }
1635 } 1662 }
1636 1663
1664 if (ctx->Extensions.ATI_envmap_bumpmap) {
1665 switch (internalFormat) {
1666 case GL_DUDV_ATI:
1667 case GL_DU8DV8_ATI:
1668 return &_mesa_texformat_dudv8;
1669 default:
1670 ; /* fallthrough */
1671 }
1672 }
1673
1637#if FEATURE_EXT_texture_sRGB 1674#if FEATURE_EXT_texture_sRGB
1638 if (ctx->Extensions.EXT_texture_sRGB) { 1675 if (ctx->Extensions.EXT_texture_sRGB) {
1639 switch (internalFormat) { 1676 switch (internalFormat) {
@@ -1778,6 +1815,11 @@ _mesa_format_to_type_and_comps(const struct gl_texture_format *format,
1778 *comps = 1; 1815 *comps = 1;
1779 return; 1816 return;
1780 1817
1818 case MESA_FORMAT_DUDV8:
1819 *datatype = GL_BYTE;
1820 *comps = 2;
1821 return;
1822
1781#if FEATURE_EXT_texture_sRGB 1823#if FEATURE_EXT_texture_sRGB
1782 case MESA_FORMAT_SRGB8: 1824 case MESA_FORMAT_SRGB8:
1783 *datatype = GL_UNSIGNED_BYTE; 1825 *datatype = GL_UNSIGNED_BYTE;
diff --git a/src/mesa/main/texformat.h b/src/mesa/main/texformat.h
index 31364c36b1a..7fa70ad4fee 100644
--- a/src/mesa/main/texformat.h
+++ b/src/mesa/main/texformat.h
@@ -161,7 +161,14 @@ enum _format {
161 MESA_FORMAT_LUMINANCE_ALPHA_FLOAT32, 161 MESA_FORMAT_LUMINANCE_ALPHA_FLOAT32,
162 MESA_FORMAT_LUMINANCE_ALPHA_FLOAT16, 162 MESA_FORMAT_LUMINANCE_ALPHA_FLOAT16,
163 MESA_FORMAT_INTENSITY_FLOAT32, 163 MESA_FORMAT_INTENSITY_FLOAT32,
164 MESA_FORMAT_INTENSITY_FLOAT16 164 MESA_FORMAT_INTENSITY_FLOAT16,
165 /*@}*/
166
167 /**
168 * \name Signed fixed point texture formats.
169 */
170 /*@{*/
171 MESA_FORMAT_DUDV8
165 /*@}*/ 172 /*@}*/
166}; 173};
167 174
@@ -209,6 +216,11 @@ extern const struct gl_texture_format _mesa_texformat_intensity_float32;
209extern const struct gl_texture_format _mesa_texformat_intensity_float16; 216extern const struct gl_texture_format _mesa_texformat_intensity_float16;
210/*@}*/ 217/*@}*/
211 218
219/** Signed fixed point texture formats */
220/*@{*/
221extern const struct gl_texture_format _mesa_texformat_dudv8;
222/*@}*/
223
212/** \name Assorted hardware-friendly formats */ 224/** \name Assorted hardware-friendly formats */
213/*@{*/ 225/*@{*/
214extern const struct gl_texture_format _mesa_texformat_rgba8888; 226extern const struct gl_texture_format _mesa_texformat_rgba8888;
diff --git a/src/mesa/main/texformat_tmp.h b/src/mesa/main/texformat_tmp.h
index 275340cabd3..f9f9d5b1f8e 100644
--- a/src/mesa/main/texformat_tmp.h
+++ b/src/mesa/main/texformat_tmp.h
@@ -1269,7 +1269,7 @@ static void FETCH(sl8)(const struct gl_texture_image *texImage,
1269 texel[RCOMP] = 1269 texel[RCOMP] =
1270 texel[GCOMP] = 1270 texel[GCOMP] =
1271 texel[BCOMP] = nonlinear_to_linear(src[0]); 1271 texel[BCOMP] = nonlinear_to_linear(src[0]);
1272 texel[ACOMP] = CHAN_MAX; 1272 texel[ACOMP] = 1.0F;
1273} 1273}
1274 1274
1275#if DIM == 3 1275#if DIM == 3
@@ -1308,7 +1308,22 @@ static void store_texel_sla8(struct gl_texture_image *texImage,
1308 1308
1309#endif /* FEATURE_EXT_texture_sRGB */ 1309#endif /* FEATURE_EXT_texture_sRGB */
1310 1310
1311#if DIM == 2
1312/* MESA_FORMAT_DUDV8 ********************************************************/
1313
1314/* this format by definition produces 0,0,0,1 as rgba values,
1315 however we'll return the dudv values as rg and fix up elsewhere */
1316static void FETCH(dudv8)(const struct gl_texture_image *texImage,
1317 GLint i, GLint j, GLint k, GLfloat *texel )
1318{
1319 const GLbyte *src = TEXEL_ADDR(GLbyte, texImage, i, j, k, 2);
1320 texel[RCOMP] = BYTE_TO_FLOAT(src[0]);
1321 texel[GCOMP] = BYTE_TO_FLOAT(src[1]);
1322 texel[BCOMP] = 0;
1323 texel[ACOMP] = 0;
1311 1324
1325}
1326#endif
1312 1327
1313/* MESA_FORMAT_YCBCR *********************************************************/ 1328/* MESA_FORMAT_YCBCR *********************************************************/
1314 1329
diff --git a/src/mesa/main/teximage.c b/src/mesa/main/teximage.c
index e3d44047598..2ed72280ec9 100644
--- a/src/mesa/main/teximage.c
+++ b/src/mesa/main/teximage.c
@@ -339,6 +339,17 @@ _mesa_base_tex_format( GLcontext *ctx, GLint internalFormat )
339 } 339 }
340 } 340 }
341 341
342 if (ctx->Extensions.ATI_envmap_bumpmap) {
343 switch (internalFormat) {
344 case GL_DUDV_ATI:
345 case GL_DU8DV8_ATI:
346 return GL_DUDV_ATI;
347 default:
348 ; /* fallthrough */
349 }
350 }
351
352
342 if (ctx->Extensions.EXT_packed_depth_stencil) { 353 if (ctx->Extensions.EXT_packed_depth_stencil) {
343 switch (internalFormat) { 354 switch (internalFormat) {
344 case GL_DEPTH_STENCIL_EXT: 355 case GL_DEPTH_STENCIL_EXT:
@@ -568,6 +579,20 @@ is_depthstencil_format(GLenum format)
568 } 579 }
569} 580}
570 581
582/**
583 * Test if the given image format is a dudv format.
584 */
585static GLboolean
586is_dudv_format(GLenum format)
587{
588 switch (format) {
589 case GL_DUDV_ATI:
590 case GL_DU8DV8_ATI:
591 return GL_TRUE;
592 default:
593 return GL_FALSE;
594 }
595}
571 596
572 597
573/** 598/**
@@ -1539,7 +1564,8 @@ texture_error_check( GLcontext *ctx, GLenum target,
1539 (is_index_format(internalFormat) && !indexFormat) || 1564 (is_index_format(internalFormat) && !indexFormat) ||
1540 (is_depth_format(internalFormat) != is_depth_format(format)) || 1565 (is_depth_format(internalFormat) != is_depth_format(format)) ||
1541 (is_ycbcr_format(internalFormat) != is_ycbcr_format(format)) || 1566 (is_ycbcr_format(internalFormat) != is_ycbcr_format(format)) ||
1542 (is_depthstencil_format(internalFormat) != is_depthstencil_format(format))) { 1567 (is_depthstencil_format(internalFormat) != is_depthstencil_format(format)) ||
1568 (is_dudv_format(internalFormat) != is_dudv_format(format))) {
1543 if (!isProxy) 1569 if (!isProxy)
1544 _mesa_error(ctx, GL_INVALID_OPERATION, 1570 _mesa_error(ctx, GL_INVALID_OPERATION,
1545 "glTexImage(internalFormat/format)"); 1571 "glTexImage(internalFormat/format)");
@@ -2273,6 +2299,12 @@ _mesa_GetTexImage( GLenum target, GLint level, GLenum format,
2273 return; 2299 return;
2274 } 2300 }
2275 2301
2302 if (!ctx->Extensions.ATI_envmap_bumpmap
2303 && is_dudv_format(format)) {
2304 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)");
2305 return;
2306 }
2307
2276 _mesa_lock_texture(ctx, texObj); 2308 _mesa_lock_texture(ctx, texObj);
2277 { 2309 {
2278 texImage = _mesa_select_tex_image(ctx, texObj, target, level); 2310 texImage = _mesa_select_tex_image(ctx, texObj, target, level);
@@ -2313,6 +2345,11 @@ _mesa_GetTexImage( GLenum target, GLint level, GLenum format,
2313 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)"); 2345 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
2314 goto out; 2346 goto out;
2315 } 2347 }
2348 else if (is_dudv_format(format)
2349 && !is_dudv_format(texImage->TexFormat->BaseFormat)) {
2350 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
2351 goto out;
2352 }
2316 2353
2317 if (ctx->Pack.BufferObj->Name) { 2354 if (ctx->Pack.BufferObj->Name) {
2318 /* packing texture image into a PBO */ 2355 /* packing texture image into a PBO */
diff --git a/src/mesa/main/texstate.c b/src/mesa/main/texstate.c
index d71f9530cb3..a5af6229104 100644
--- a/src/mesa/main/texstate.c
+++ b/src/mesa/main/texstate.c
@@ -95,6 +95,11 @@ _mesa_copy_texture_state( const GLcontext *src, GLcontext *dst )
95 /* GL_EXT_texture_env_combine */ 95 /* GL_EXT_texture_env_combine */
96 dst->Texture.Unit[u].Combine = src->Texture.Unit[u].Combine; 96 dst->Texture.Unit[u].Combine = src->Texture.Unit[u].Combine;
97 97
98 /* GL_ATI_envmap_bumpmap - need this? */
99 dst->Texture.Unit[u].BumpTarget = src->Texture.Unit[u].BumpTarget;
100 COPY_4V(dst->Texture.Unit[u].RotMatrix, src->Texture.Unit[u].RotMatrix);
101
102
98 /* copy texture object bindings, not contents of texture objects */ 103 /* copy texture object bindings, not contents of texture objects */
99 _mesa_lock_context_textures(dst); 104 _mesa_lock_context_textures(dst);
100 105
@@ -411,6 +416,10 @@ update_tex_combine(GLcontext *ctx, struct gl_texture_unit *texUnit)
411 case GL_MODULATE_SUBTRACT_ATI: 416 case GL_MODULATE_SUBTRACT_ATI:
412 combine->_NumArgsRGB = 3; 417 combine->_NumArgsRGB = 3;
413 break; 418 break;
419 case GL_BUMP_ENVMAP_ATI:
420 /* no real arguments for this case */
421 combine->_NumArgsRGB = 0;
422 break;
414 default: 423 default:
415 combine->_NumArgsRGB = 0; 424 combine->_NumArgsRGB = 0;
416 _mesa_problem(ctx, "invalid RGB combine mode in update_texture_state"); 425 _mesa_problem(ctx, "invalid RGB combine mode in update_texture_state");
@@ -682,6 +691,7 @@ init_texture_unit( GLcontext *ctx, GLuint unit )
682 texUnit->Combine = default_combine_state; 691 texUnit->Combine = default_combine_state;
683 texUnit->_EnvMode = default_combine_state; 692 texUnit->_EnvMode = default_combine_state;
684 texUnit->_CurrentCombine = & texUnit->_EnvMode; 693 texUnit->_CurrentCombine = & texUnit->_EnvMode;
694 texUnit->BumpTarget = GL_TEXTURE0;
685 695
686 texUnit->TexGenEnabled = 0x0; 696 texUnit->TexGenEnabled = 0x0;
687 texUnit->GenS.Mode = GL_EYE_LINEAR; 697 texUnit->GenS.Mode = GL_EYE_LINEAR;
@@ -702,6 +712,16 @@ init_texture_unit( GLcontext *ctx, GLuint unit )
702 ASSIGN_4V( texUnit->GenT.EyePlane, 0.0, 1.0, 0.0, 0.0 ); 712 ASSIGN_4V( texUnit->GenT.EyePlane, 0.0, 1.0, 0.0, 0.0 );
703 ASSIGN_4V( texUnit->GenR.EyePlane, 0.0, 0.0, 0.0, 0.0 ); 713 ASSIGN_4V( texUnit->GenR.EyePlane, 0.0, 0.0, 0.0, 0.0 );
704 ASSIGN_4V( texUnit->GenQ.EyePlane, 0.0, 0.0, 0.0, 0.0 ); 714 ASSIGN_4V( texUnit->GenQ.EyePlane, 0.0, 0.0, 0.0, 0.0 );
715 ASSIGN_4V( texUnit->GenS.ObjectPlane, 1.0, 0.0, 0.0, 0.0 );
716 ASSIGN_4V( texUnit->GenT.ObjectPlane, 0.0, 1.0, 0.0, 0.0 );
717 ASSIGN_4V( texUnit->GenR.ObjectPlane, 0.0, 0.0, 0.0, 0.0 );
718 ASSIGN_4V( texUnit->GenQ.ObjectPlane, 0.0, 0.0, 0.0, 0.0 );
719 ASSIGN_4V( texUnit->GenS.EyePlane, 1.0, 0.0, 0.0, 0.0 );
720 ASSIGN_4V( texUnit->GenT.EyePlane, 0.0, 1.0, 0.0, 0.0 );
721 ASSIGN_4V( texUnit->GenR.EyePlane, 0.0, 0.0, 0.0, 0.0 );
722 ASSIGN_4V( texUnit->GenQ.EyePlane, 0.0, 0.0, 0.0, 0.0 );
723 /* no mention of this in spec, but maybe id matrix expected? */
724 ASSIGN_4V( texUnit->RotMatrix, 1.0, 0.0, 0.0, 1.0 );
705 725
706 /* initialize current texture object ptrs to the shared default objects */ 726 /* initialize current texture object ptrs to the shared default objects */
707 for (tex = 0; tex < NUM_TEXTURE_TARGETS; tex++) { 727 for (tex = 0; tex < NUM_TEXTURE_TARGETS; tex++) {
diff --git a/src/mesa/main/texstore.c b/src/mesa/main/texstore.c
index 6360ca15f81..cc3c6958c7d 100644
--- a/src/mesa/main/texstore.c
+++ b/src/mesa/main/texstore.c
@@ -2471,6 +2471,95 @@ _mesa_texstore_ycbcr(TEXSTORE_PARAMS)
2471 return GL_TRUE; 2471 return GL_TRUE;
2472} 2472}
2473 2473
2474GLboolean
2475_mesa_texstore_dudv8(TEXSTORE_PARAMS)
2476{
2477 const GLboolean littleEndian = _mesa_little_endian();
2478
2479 ASSERT(dstFormat == &_mesa_texformat_dudv8);
2480 ASSERT(dstFormat->TexelBytes == 2);
2481 ASSERT(ctx->Extensions.ATI_envmap_bumpmap);
2482 ASSERT((srcFormat == GL_DU8DV8_ATI) ||
2483 (srcFormat == GL_DUDV_ATI));
2484 ASSERT(baseInternalFormat == GL_DUDV_ATI);
2485
2486 if (!srcPacking->SwapBytes && srcType == GL_BYTE &&
2487 littleEndian) {
2488 /* simple memcpy path */
2489 memcpy_texture(ctx, dims,
2490 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
2491 dstRowStride,
2492 dstImageOffsets,
2493 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
2494 srcAddr, srcPacking);
2495 }
2496 else if (srcType == GL_BYTE) {
2497
2498 GLubyte dstmap[4];
2499
2500 /* dstmap - how to swizzle from RGBA to dst format:
2501 */
2502 if (littleEndian) {
2503 dstmap[0] = 0;
2504 dstmap[1] = 3;
2505 }
2506 else {
2507 dstmap[0] = 3;
2508 dstmap[1] = 0;
2509 }
2510 dstmap[2] = ZERO; /* ? */
2511 dstmap[3] = ONE; /* ? */
2512
2513 _mesa_swizzle_ubyte_image(ctx, dims,
2514 GL_LUMINANCE_ALPHA, /* hack */
2515 GL_UNSIGNED_BYTE, /* hack */
2516 GL_LUMINANCE_ALPHA, /* hack */
2517 dstmap, 2,
2518 dstAddr, dstXoffset, dstYoffset, dstZoffset,
2519 dstRowStride, dstImageOffsets,
2520 srcWidth, srcHeight, srcDepth, srcAddr,
2521 srcPacking);
2522 }
2523 else {
2524 /* general path - note this is defined for 2d textures only */
2525 const GLint components = _mesa_components_in_format(baseInternalFormat);
2526 const GLint srcStride = _mesa_image_row_stride(srcPacking,
2527 srcWidth, srcFormat, srcType);
2528 GLbyte *tempImage, *dst, *src;
2529 GLint row;
2530
2531 tempImage = (GLbyte *) _mesa_malloc(srcWidth * srcHeight * srcDepth
2532 * components * sizeof(GLbyte));
2533 if (!tempImage)
2534 return GL_FALSE;
2535
2536 src = (GLbyte *) _mesa_image_address(dims, srcPacking, srcAddr,
2537 srcWidth, srcHeight,
2538 srcFormat, srcType,
2539 0, 0, 0);
2540
2541 dst = tempImage;
2542 for (row = 0; row < srcHeight; row++) {
2543 _mesa_unpack_dudv_span_byte(ctx, srcWidth, baseInternalFormat,
2544 dst, srcFormat, srcType, src,
2545 srcPacking, 0);
2546 dst += srcWidth * components;
2547 src += srcStride;
2548 }
2549
2550 src = tempImage;
2551 dst = (GLbyte *) dstAddr
2552 + dstYoffset * dstRowStride
2553 + dstXoffset * dstFormat->TexelBytes;
2554 for (row = 0; row < srcHeight; row++) {
2555 memcpy(dst, src, srcWidth * dstFormat->TexelBytes);
2556 dst += dstRowStride;
2557 src += srcWidth * dstFormat->TexelBytes;
2558 }
2559 _mesa_free((void *) tempImage);
2560 }
2561 return GL_TRUE;
2562}
2474 2563
2475 2564
2476/** 2565/**
@@ -3882,7 +3971,7 @@ _mesa_get_teximage(GLcontext *ctx, GLenum target, GLint level,
3882 GLint col; 3971 GLint col;
3883 GLbitfield transferOps = 0x0; 3972 GLbitfield transferOps = 0x0;
3884 3973
3885 if (type == GL_FLOAT && 3974 if (type == GL_FLOAT && texImage->TexFormat->BaseFormat != GL_DUDV_ATI &&
3886 ((ctx->Color.ClampReadColor == GL_TRUE) || 3975 ((ctx->Color.ClampReadColor == GL_TRUE) ||
3887 (ctx->Color.ClampReadColor == GL_FIXED_ONLY_ARB && 3976 (ctx->Color.ClampReadColor == GL_FIXED_ONLY_ARB &&
3888 texImage->TexFormat->DataType != GL_FLOAT))) 3977 texImage->TexFormat->DataType != GL_FLOAT)))
diff --git a/src/mesa/main/texstore.h b/src/mesa/main/texstore.h
index b03386b2acc..c9e639be4e0 100644
--- a/src/mesa/main/texstore.h
+++ b/src/mesa/main/texstore.h
@@ -78,7 +78,7 @@ extern GLboolean _mesa_texstore_sargb8(TEXSTORE_PARAMS);
78extern GLboolean _mesa_texstore_sl8(TEXSTORE_PARAMS); 78extern GLboolean _mesa_texstore_sl8(TEXSTORE_PARAMS);
79extern GLboolean _mesa_texstore_sla8(TEXSTORE_PARAMS); 79extern GLboolean _mesa_texstore_sla8(TEXSTORE_PARAMS);
80#endif 80#endif
81 81extern GLboolean _mesa_texstore_dudv8(TEXSTORE_PARAMS);
82 82
83extern GLchan * 83extern GLchan *
84_mesa_make_temp_chan_image(GLcontext *ctx, GLuint dims, 84_mesa_make_temp_chan_image(GLcontext *ctx, GLuint dims,
diff --git a/src/mesa/shader/prog_statevars.c b/src/mesa/shader/prog_statevars.c
index 1f7d87ccc94..f51d9e26512 100644
--- a/src/mesa/shader/prog_statevars.c
+++ b/src/mesa/shader/prog_statevars.c
@@ -506,6 +506,26 @@ _mesa_fetch_state(GLcontext *ctx, const gl_state_index state[],
506 } 506 }
507 } 507 }
508 return; 508 return;
509 case STATE_ROT_MATRIX_0:
510 {
511 const int unit = (int) state[2];
512 GLfloat *rotMat22 = ctx->Texture.Unit[unit].RotMatrix;
513 value[0] = rotMat22[0];
514 value[1] = rotMat22[2];
515 value[2] = 0.0;
516 value[3] = 0.0;
517 }
518 break;
519 case STATE_ROT_MATRIX_1:
520 {
521 const int unit = (int) state[2];
522 GLfloat *rotMat22 = ctx->Texture.Unit[unit].RotMatrix;
523 value[0] = rotMat22[1];
524 value[1] = rotMat22[3];
525 value[2] = 0.0;
526 value[3] = 0.0;
527 }
528 break;
509 529
510 /* XXX: make sure new tokens added here are also handled in the 530 /* XXX: make sure new tokens added here are also handled in the
511 * _mesa_program_state_flags() switch, below. 531 * _mesa_program_state_flags() switch, below.
@@ -591,6 +611,8 @@ _mesa_program_state_flags(const gl_state_index state[STATE_LENGTH])
591 611
592 case STATE_TEXRECT_SCALE: 612 case STATE_TEXRECT_SCALE:
593 case STATE_SHADOW_AMBIENT: 613 case STATE_SHADOW_AMBIENT:
614 case STATE_ROT_MATRIX_0:
615 case STATE_ROT_MATRIX_1:
594 return _NEW_TEXTURE; 616 return _NEW_TEXTURE;
595 case STATE_FOG_PARAMS_OPTIMIZED: 617 case STATE_FOG_PARAMS_OPTIMIZED:
596 return _NEW_FOG; 618 return _NEW_FOG;
@@ -806,6 +828,12 @@ append_token(char *dst, gl_state_index k)
806 case STATE_SHADOW_AMBIENT: 828 case STATE_SHADOW_AMBIENT:
807 append(dst, "CompareFailValue"); 829 append(dst, "CompareFailValue");
808 break; 830 break;
831 case STATE_ROT_MATRIX_0:
832 append(dst, "rotMatrixRow0");
833 break;
834 case STATE_ROT_MATRIX_1:
835 append(dst, "rotMatrixRow1");
836 break;
809 default: 837 default:
810 /* probably STATE_INTERNAL_DRIVER+i (driver private state) */ 838 /* probably STATE_INTERNAL_DRIVER+i (driver private state) */
811 append(dst, "driverState"); 839 append(dst, "driverState");
diff --git a/src/mesa/shader/prog_statevars.h b/src/mesa/shader/prog_statevars.h
index d5358a1d042..d563080db1c 100644
--- a/src/mesa/shader/prog_statevars.h
+++ b/src/mesa/shader/prog_statevars.h
@@ -117,6 +117,8 @@ typedef enum gl_state_index_ {
117 STATE_PCM_SCALE, /**< Post color matrix RGBA scale */ 117 STATE_PCM_SCALE, /**< Post color matrix RGBA scale */
118 STATE_PCM_BIAS, /**< Post color matrix RGBA bias */ 118 STATE_PCM_BIAS, /**< Post color matrix RGBA bias */
119 STATE_SHADOW_AMBIENT, /**< ARB_shadow_ambient fail value; token[2] is texture unit index */ 119 STATE_SHADOW_AMBIENT, /**< ARB_shadow_ambient fail value; token[2] is texture unit index */
120 STATE_ROT_MATRIX_0, /**< ATI_envmap_bumpmap, rot matrix row 0 */
121 STATE_ROT_MATRIX_1, /**< ATI_envmap_bumpmap, rot matrix row 1 */
120 STATE_INTERNAL_DRIVER /* first available state index for drivers (must be last) */ 122 STATE_INTERNAL_DRIVER /* first available state index for drivers (must be last) */
121} gl_state_index; 123} gl_state_index;
122 124
diff --git a/src/mesa/swrast/s_texcombine.c b/src/mesa/swrast/s_texcombine.c
index 38b5633887f..aa28311672d 100644
--- a/src/mesa/swrast/s_texcombine.c
+++ b/src/mesa/swrast/s_texcombine.c
@@ -591,6 +591,25 @@ texture_combine( const GLcontext *ctx, GLuint unit, GLuint n,
591 } 591 }
592 } 592 }
593 break; 593 break;
594 case GL_BUMP_ENVMAP_ATI:
595 {
596 /* this produces a fixed rgba color, and the coord calc is done elsewhere */
597 for (i = 0; i < n; i++) {
598 /* rgba result is 0,0,0,1 */
599#if CHAN_TYPE == GL_FLOAT
600 rgba[i][RCOMP] = 0.0;
601 rgba[i][GCOMP] = 0.0;
602 rgba[i][BCOMP] = 0.0;
603 rgba[i][ACOMP] = 1.0;
604#else
605 rgba[i][RCOMP] = 0;
606 rgba[i][GCOMP] = 0;
607 rgba[i][BCOMP] = 0;
608 rgba[i][ACOMP] = CHAN_MAX;
609#endif
610 }
611 }
612 return; /* no alpha processing */
594 default: 613 default:
595 _mesa_problem(ctx, "invalid combine mode"); 614 _mesa_problem(ctx, "invalid combine mode");
596 } 615 }
@@ -1218,12 +1237,86 @@ _swrast_texture_span( GLcontext *ctx, SWspan *span )
1218 if (swrast->_AnyTextureCombine) 1237 if (swrast->_AnyTextureCombine)
1219 MEMCPY(primary_rgba, span->array->rgba, 4 * span->end * sizeof(GLchan)); 1238 MEMCPY(primary_rgba, span->array->rgba, 4 * span->end * sizeof(GLchan));
1220 1239
1240 /* First must sample all bump maps */
1241 for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
1242 if (ctx->Texture.Unit[unit]._ReallyEnabled &&
1243 ctx->Texture.Unit[unit]._CurrentCombine->ModeRGB == GL_BUMP_ENVMAP_ATI) {
1244 const GLfloat (*texcoords)[4]
1245 = (const GLfloat (*)[4])
1246 span->array->attribs[FRAG_ATTRIB_TEX0 + unit];
1247 GLfloat (*targetcoords)[4]
1248 = (GLfloat (*)[4])
1249 span->array->attribs[FRAG_ATTRIB_TEX0 +
1250 ctx->Texture.Unit[unit].BumpTarget - GL_TEXTURE0];
1251
1252 const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
1253 const struct gl_texture_object *curObj = texUnit->_Current;
1254 GLfloat *lambda = span->array->lambda[unit];
1255 GLchan (*texels)[4] = (GLchan (*)[4])
1256 (swrast->TexelBuffer + unit * (span->end * 4 * sizeof(GLchan)));
1257 GLuint i;
1258 GLfloat rotMatrix00 = ctx->Texture.Unit[unit].RotMatrix[0];
1259 GLfloat rotMatrix01 = ctx->Texture.Unit[unit].RotMatrix[1];
1260 GLfloat rotMatrix10 = ctx->Texture.Unit[unit].RotMatrix[2];
1261 GLfloat rotMatrix11 = ctx->Texture.Unit[unit].RotMatrix[3];
1262
1263 /* adjust texture lod (lambda) */
1264 if (span->arrayMask & SPAN_LAMBDA) {
1265 if (texUnit->LodBias + curObj->LodBias != 0.0F) {
1266 /* apply LOD bias, but don't clamp yet */
1267 const GLfloat bias = CLAMP(texUnit->LodBias + curObj->LodBias,
1268 -ctx->Const.MaxTextureLodBias,
1269 ctx->Const.MaxTextureLodBias);
1270 GLuint i;
1271 for (i = 0; i < span->end; i++) {
1272 lambda[i] += bias;
1273 }
1274 }
1275
1276 if (curObj->MinLod != -1000.0 || curObj->MaxLod != 1000.0) {
1277 /* apply LOD clamping to lambda */
1278 const GLfloat min = curObj->MinLod;
1279 const GLfloat max = curObj->MaxLod;
1280 GLuint i;
1281 for (i = 0; i < span->end; i++) {
1282 GLfloat l = lambda[i];
1283 lambda[i] = CLAMP(l, min, max);
1284 }
1285 }
1286 }
1287
1288 /* Sample the texture (span->end = number of fragments) */
1289 swrast->TextureSample[unit]( ctx, texUnit->_Current, span->end,
1290 texcoords, lambda, texels );
1291
1292 /* manipulate the span values of the bump target
1293 not sure this can work correctly even ignoring
1294 the problem that channel is unsigned */
1295 for (i = 0; i < span->end; i++) {
1296#if CHAN_TYPE == GL_FLOAT
1297 targetcoords[i][0] += (texels[i][0] * rotMatrix00 + texels[i][1] *
1298 rotMatrix01) / targetcoords[i][3];
1299 targetcoords[i][1] += (texels[i][0] * rotMatrix10 + texels[i][1] *
1300 rotMatrix11) / targetcoords[i][3];
1301#else
1302 targetcoords[i][0] += (CHAN_TO_FLOAT(texels[i][1]) * rotMatrix00 +
1303 CHAN_TO_FLOAT(texels[i][1]) * rotMatrix01) /
1304 targetcoords[i][3];
1305 targetcoords[i][1] += (CHAN_TO_FLOAT(texels[i][0]) * rotMatrix10 +
1306 CHAN_TO_FLOAT(texels[i][1]) * rotMatrix11) /
1307 targetcoords[i][3];
1308#endif
1309 }
1310 }
1311 }
1312
1221 /* 1313 /*
1222 * Must do all texture sampling before combining in order to 1314 * Must do all texture sampling before combining in order to
1223 * accomodate GL_ARB_texture_env_crossbar. 1315 * accomodate GL_ARB_texture_env_crossbar.
1224 */ 1316 */
1225 for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) { 1317 for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
1226 if (ctx->Texture.Unit[unit]._ReallyEnabled) { 1318 if (ctx->Texture.Unit[unit]._ReallyEnabled &&
1319 ctx->Texture.Unit[unit]._CurrentCombine->ModeRGB != GL_BUMP_ENVMAP_ATI) {
1227 const GLfloat (*texcoords)[4] 1320 const GLfloat (*texcoords)[4]
1228 = (const GLfloat (*)[4]) 1321 = (const GLfloat (*)[4])
1229 span->array->attribs[FRAG_ATTRIB_TEX0 + unit]; 1322 span->array->attribs[FRAG_ATTRIB_TEX0 + unit];