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)
This commit is contained in:
@@ -11681,6 +11681,56 @@
|
||||
<enum name="DEPTH_STENCIL_TO_BGRA_NV" value="0x886F"/>
|
||||
</category>
|
||||
|
||||
<category name="GL_ATI_envmap_bumpmap" number="244">
|
||||
<enum name="BUMP_ROT_MATRIX_ATI" count="4" value="0x8775">
|
||||
<size name="TexBumpParameterfv"/>
|
||||
<size name="TexBumpParameteriv"/>
|
||||
<size name="GetTexBumpParameterfv" mode="get"/>
|
||||
<size name="GetTexBumpParameteriv" mode="get"/>
|
||||
</enum>
|
||||
<enum name="BUMP_ROT_MATRIX_SIZE_ATI" count="1" value="0x8776">
|
||||
<size name="GetTexBumpParameterfv" mode="get"/>
|
||||
<size name="GetTexBumpParameteriv" mode="get"/>
|
||||
</enum>
|
||||
<enum name="BUMP_NUM_TEX_UNITS_ATI" count="1" value="0x8777">
|
||||
<size name="GetTexBumpParameterfv" mode="get"/>
|
||||
<size name="GetTexBumpParameteriv" mode="get"/>
|
||||
</enum>
|
||||
<enum name="BUMP_TEX_UNITS_ATI" count="-1" value="0x8778">
|
||||
<size name="GetTexBumpParameterfv" mode="get"/>
|
||||
<size name="GetTexBumpParameteriv" mode="get"/>
|
||||
</enum>
|
||||
<enum name="DUDV_ATI" value="0x8779"/>
|
||||
<enum name="DU8DV8_ATI" value="0x877A"/>
|
||||
<enum name="BUMP_ENVMAP_ATI" value="0x877B"/>
|
||||
<enum name="BUMP_TARGET_ATI" count="1" value="0x877C">
|
||||
<size name="TexEnviv"/>
|
||||
<size name="TexEnvfv"/>
|
||||
<size name="GetTexEnviv" mode="get"/>
|
||||
<size name="GetTexEnvfv" mode="get"/>
|
||||
</enum>
|
||||
<function name="TexBumpParameterfvATI" offset="assign">
|
||||
<param name="pname" type="GLenum"/>
|
||||
<param name="param" type="const GLfloat *" variable_param="pname"/>
|
||||
<glx ignore="true"/>
|
||||
</function>
|
||||
<function name="TexBumpParameterivATI" offset="assign">
|
||||
<param name="pname" type="GLenum"/>
|
||||
<param name="param" type="const GLint *" variable_param="pname"/>
|
||||
<glx ignore="true"/>
|
||||
</function>
|
||||
<function name="GetTexBumpParameterfvATI" offset="assign">
|
||||
<param name="pname" type="GLenum"/>
|
||||
<param name="param" type="GLfloat *" variable_param="pname"/>
|
||||
<glx ignore="true"/>
|
||||
</function>
|
||||
<function name="GetTexBumpParameterivATI" offset="assign">
|
||||
<param name="pname" type="GLenum"/>
|
||||
<param name="param" type="GLint *" variable_param="pname"/>
|
||||
<glx ignore="true"/>
|
||||
</function>
|
||||
</category>
|
||||
|
||||
<category name="GL_ATI_fragment_shader" number="245">
|
||||
<function name="GenFragmentShadersATI" offset="assign">
|
||||
<return type="GLuint"/>
|
||||
|
@@ -839,6 +839,12 @@ _mesa_init_exec_table(struct _glapi_table *exec)
|
||||
SET_SetFragmentShaderConstantATI(exec, _mesa_SetFragmentShaderConstantATI);
|
||||
#endif
|
||||
|
||||
/* GL_ATI_envmap_bumpmap */
|
||||
SET_GetTexBumpParameterivATI(exec, _mesa_GetTexBumpParameterivATI);
|
||||
SET_GetTexBumpParameterfvATI(exec, _mesa_GetTexBumpParameterfvATI);
|
||||
SET_TexBumpParameterivATI(exec, _mesa_TexBumpParameterivATI);
|
||||
SET_TexBumpParameterfvATI(exec, _mesa_TexBumpParameterfvATI);
|
||||
|
||||
#if FEATURE_EXT_framebuffer_object
|
||||
SET_IsRenderbufferEXT(exec, _mesa_IsRenderbufferEXT);
|
||||
SET_BindRenderbufferEXT(exec, _mesa_BindRenderbufferEXT);
|
||||
|
@@ -232,7 +232,8 @@
|
||||
#define MAX_COLOR_ATTACHMENTS 8
|
||||
/*@}*/
|
||||
|
||||
|
||||
/** For GL_ATI_envmap_bump - support bump mapping on first 8 units */
|
||||
#define SUPPORTED_ATI_BUMP_UNITS 0xff
|
||||
|
||||
/**
|
||||
* \name Mesa-specific parameters
|
||||
|
@@ -589,6 +589,9 @@ _mesa_init_constants(GLcontext *ctx)
|
||||
/* GL_ARB_framebuffer_object */
|
||||
ctx->Const.MaxSamples = 0;
|
||||
|
||||
/* GL_ATI_envmap_bumpmap */
|
||||
ctx->Const.SupportedBumpUnits = SUPPORTED_ATI_BUMP_UNITS;
|
||||
|
||||
/* sanity checks */
|
||||
ASSERT(ctx->Const.MaxTextureUnits == MIN2(ctx->Const.MaxTextureImageUnits,
|
||||
ctx->Const.MaxTextureCoordUnits));
|
||||
|
@@ -320,6 +320,8 @@ typedef enum
|
||||
/* GL_ARB_draw_buffers */
|
||||
OPCODE_DRAW_BUFFERS_ARB,
|
||||
/* GL_ATI_fragment_shader */
|
||||
OPCODE_TEX_BUMP_PARAMETER_ATI,
|
||||
/* GL_ATI_fragment_shader */
|
||||
OPCODE_BIND_FRAGMENT_SHADER_ATI,
|
||||
OPCODE_SET_FRAGMENT_SHADER_CONSTANTS_ATI,
|
||||
/* OpenGL 2.0 */
|
||||
@@ -4803,6 +4805,36 @@ save_DrawBuffersARB(GLsizei count, const GLenum * buffers)
|
||||
}
|
||||
}
|
||||
|
||||
static void GLAPIENTRY
|
||||
save_TexBumpParameterfvATI(GLenum pname, const GLfloat *param)
|
||||
{
|
||||
GET_CURRENT_CONTEXT(ctx);
|
||||
Node *n;
|
||||
|
||||
n = ALLOC_INSTRUCTION(ctx, OPCODE_TEX_BUMP_PARAMETER_ATI, 5);
|
||||
if (n) {
|
||||
n[1].ui = pname;
|
||||
n[2].f = param[0];
|
||||
n[3].f = param[1];
|
||||
n[4].f = param[2];
|
||||
n[5].f = param[3];
|
||||
}
|
||||
if (ctx->ExecuteFlag) {
|
||||
CALL_TexBumpParameterfvATI(ctx->Exec, (pname, param));
|
||||
}
|
||||
}
|
||||
|
||||
static void GLAPIENTRY
|
||||
save_TexBumpParameterivATI(GLenum pname, const GLint *param)
|
||||
{
|
||||
GLfloat p[4];
|
||||
p[0] = INT_TO_FLOAT(param[0]);
|
||||
p[1] = INT_TO_FLOAT(param[1]);
|
||||
p[2] = INT_TO_FLOAT(param[2]);
|
||||
p[3] = INT_TO_FLOAT(param[3]);
|
||||
save_TexBumpParameterfvATI(pname, p);
|
||||
}
|
||||
|
||||
#if FEATURE_ATI_fragment_shader
|
||||
static void GLAPIENTRY
|
||||
save_BindFragmentShaderATI(GLuint id)
|
||||
@@ -6505,6 +6537,16 @@ execute_list(GLcontext *ctx, GLuint list)
|
||||
n[9].i, n[10].e));
|
||||
break;
|
||||
#endif
|
||||
case OPCODE_TEX_BUMP_PARAMETER_ATI:
|
||||
{
|
||||
GLfloat values[4];
|
||||
GLuint i, pname = n[1].ui;
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
values[i] = n[1 + i].f;
|
||||
CALL_TexBumpParameterfvATI(ctx->Exec, (pname, values));
|
||||
}
|
||||
break;
|
||||
#if FEATURE_ATI_fragment_shader
|
||||
case OPCODE_BIND_FRAGMENT_SHADER_ATI:
|
||||
CALL_BindFragmentShaderATI(ctx->Exec, (n[1].i));
|
||||
@@ -8043,6 +8085,10 @@ _mesa_init_dlist_table(struct _glapi_table *table)
|
||||
SET_VertexAttribPointerNV(table, _mesa_VertexAttribPointerNV);
|
||||
#endif
|
||||
|
||||
/* 244. GL_ATI_envmap_bumpmap */
|
||||
SET_TexBumpParameterivATI(table, save_TexBumpParameterivATI);
|
||||
SET_TexBumpParameterfvATI(table, save_TexBumpParameterfvATI);
|
||||
|
||||
/* 245. GL_ATI_fragment_shader */
|
||||
#if FEATURE_ATI_fragment_shader
|
||||
SET_BindFragmentShaderATI(table, save_BindFragmentShaderATI);
|
||||
|
@@ -137,6 +137,7 @@ static const struct {
|
||||
{ ON, "GL_APPLE_packed_pixels", F(APPLE_packed_pixels) },
|
||||
{ OFF, "GL_APPLE_vertex_array_object", F(APPLE_vertex_array_object) },
|
||||
{ OFF, "GL_ATI_blend_equation_separate", F(EXT_blend_equation_separate) },
|
||||
{ OFF, "GL_ATI_envmap_bumpmap", F(ATI_envmap_bumpmap) },
|
||||
{ OFF, "GL_ATI_texture_env_combine3", F(ATI_texture_env_combine3)},
|
||||
{ OFF, "GL_ATI_texture_mirror_once", F(ATI_texture_mirror_once)},
|
||||
{ OFF, "GL_ATI_fragment_shader", F(ATI_fragment_shader)},
|
||||
@@ -229,6 +230,7 @@ _mesa_enable_sw_extensions(GLcontext *ctx)
|
||||
/*ctx->Extensions.ARB_vertex_buffer_object = GL_TRUE;*/
|
||||
#endif
|
||||
ctx->Extensions.APPLE_vertex_array_object = GL_TRUE;
|
||||
ctx->Extensions.ATI_envmap_bumpmap = GL_TRUE;
|
||||
#if FEATURE_ATI_fragment_shader
|
||||
ctx->Extensions.ATI_fragment_shader = GL_TRUE;
|
||||
#endif
|
||||
|
@@ -293,6 +293,8 @@ _mesa_components_in_format( GLenum format )
|
||||
return 2;
|
||||
case GL_DEPTH_STENCIL_EXT:
|
||||
return 2;
|
||||
case GL_DUDV_ATI:
|
||||
return 2;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
@@ -503,6 +505,20 @@ _mesa_is_legal_format_and_type( GLcontext *ctx, GLenum format, GLenum type )
|
||||
return GL_TRUE;
|
||||
else
|
||||
return GL_FALSE;
|
||||
case GL_DUDV_ATI:
|
||||
case GL_DU8DV8_ATI:
|
||||
switch (type) {
|
||||
case GL_BYTE:
|
||||
case GL_UNSIGNED_BYTE:
|
||||
case GL_SHORT:
|
||||
case GL_UNSIGNED_SHORT:
|
||||
case GL_INT:
|
||||
case GL_UNSIGNED_INT:
|
||||
case GL_FLOAT:
|
||||
return GL_TRUE;
|
||||
default:
|
||||
return GL_FALSE;
|
||||
}
|
||||
default:
|
||||
; /* fall-through */
|
||||
}
|
||||
@@ -1674,8 +1690,19 @@ _mesa_pack_rgba_span_float(GLcontext *ctx, GLuint n, GLfloat rgba[][4],
|
||||
GLfloat luminance[MAX_WIDTH];
|
||||
const GLint comps = _mesa_components_in_format(dstFormat);
|
||||
GLuint i;
|
||||
|
||||
if (dstType != GL_FLOAT || ctx->Color.ClampReadColor == GL_TRUE) {
|
||||
/* clamping only applies to colors, not the dudv values, but still need
|
||||
it if converting to unsigned values (which doesn't make much sense) */
|
||||
if (dstFormat == GL_DUDV_ATI || dstFormat == GL_DU8DV8_ATI) {
|
||||
switch (dstType) {
|
||||
case GL_UNSIGNED_BYTE:
|
||||
case GL_UNSIGNED_SHORT:
|
||||
case GL_UNSIGNED_INT:
|
||||
transferOps |= IMAGE_CLAMP_BIT;
|
||||
break;
|
||||
/* actually might want clamp to [-1,1] otherwise but shouldn't matter? */
|
||||
}
|
||||
}
|
||||
else if (dstType != GL_FLOAT || ctx->Color.ClampReadColor == GL_TRUE) {
|
||||
/* need to clamp to [0, 1] */
|
||||
transferOps |= IMAGE_CLAMP_BIT;
|
||||
}
|
||||
@@ -1774,6 +1801,13 @@ _mesa_pack_rgba_span_float(GLcontext *ctx, GLuint n, GLfloat rgba[][4],
|
||||
dst[i*4+3] = FLOAT_TO_UBYTE(rgba[i][RCOMP]);
|
||||
}
|
||||
break;
|
||||
case GL_DUDV_ATI:
|
||||
case GL_DU8DV8_ATI:
|
||||
for (i=0;i<n;i++) {
|
||||
dst[i*2+0] = FLOAT_TO_UBYTE(rgba[i][RCOMP]);
|
||||
dst[i*2+1] = FLOAT_TO_UBYTE(rgba[i][GCOMP]);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
_mesa_problem(ctx, "bad format in _mesa_pack_rgba_span\n");
|
||||
}
|
||||
@@ -1847,6 +1881,13 @@ _mesa_pack_rgba_span_float(GLcontext *ctx, GLuint n, GLfloat rgba[][4],
|
||||
dst[i*4+3] = FLOAT_TO_BYTE(rgba[i][RCOMP]);
|
||||
}
|
||||
break;
|
||||
case GL_DUDV_ATI:
|
||||
case GL_DU8DV8_ATI:
|
||||
for (i=0;i<n;i++) {
|
||||
dst[i*2+0] = FLOAT_TO_BYTE(rgba[i][RCOMP]);
|
||||
dst[i*2+1] = FLOAT_TO_BYTE(rgba[i][GCOMP]);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
_mesa_problem(ctx, "bad format in _mesa_pack_rgba_span\n");
|
||||
}
|
||||
@@ -1920,6 +1961,13 @@ _mesa_pack_rgba_span_float(GLcontext *ctx, GLuint n, GLfloat rgba[][4],
|
||||
CLAMPED_FLOAT_TO_USHORT(dst[i*4+3], rgba[i][RCOMP]);
|
||||
}
|
||||
break;
|
||||
case GL_DUDV_ATI:
|
||||
case GL_DU8DV8_ATI:
|
||||
for (i=0;i<n;i++) {
|
||||
dst[i*2+0] = FLOAT_TO_USHORT(rgba[i][RCOMP]);
|
||||
dst[i*2+1] = FLOAT_TO_USHORT(rgba[i][GCOMP]);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
_mesa_problem(ctx, "bad format in _mesa_pack_rgba_span\n");
|
||||
}
|
||||
@@ -1993,6 +2041,13 @@ _mesa_pack_rgba_span_float(GLcontext *ctx, GLuint n, GLfloat rgba[][4],
|
||||
dst[i*4+3] = FLOAT_TO_SHORT(rgba[i][RCOMP]);
|
||||
}
|
||||
break;
|
||||
case GL_DUDV_ATI:
|
||||
case GL_DU8DV8_ATI:
|
||||
for (i=0;i<n;i++) {
|
||||
dst[i*2+0] = FLOAT_TO_SHORT(rgba[i][RCOMP]);
|
||||
dst[i*2+1] = FLOAT_TO_SHORT(rgba[i][GCOMP]);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
_mesa_problem(ctx, "bad format in _mesa_pack_rgba_span\n");
|
||||
}
|
||||
@@ -2066,6 +2121,13 @@ _mesa_pack_rgba_span_float(GLcontext *ctx, GLuint n, GLfloat rgba[][4],
|
||||
dst[i*4+3] = FLOAT_TO_UINT(rgba[i][RCOMP]);
|
||||
}
|
||||
break;
|
||||
case GL_DUDV_ATI:
|
||||
case GL_DU8DV8_ATI:
|
||||
for (i=0;i<n;i++) {
|
||||
dst[i*2+0] = FLOAT_TO_UINT(rgba[i][RCOMP]);
|
||||
dst[i*2+1] = FLOAT_TO_UINT(rgba[i][GCOMP]);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
_mesa_problem(ctx, "bad format in _mesa_pack_rgba_span\n");
|
||||
}
|
||||
@@ -2139,6 +2201,13 @@ _mesa_pack_rgba_span_float(GLcontext *ctx, GLuint n, GLfloat rgba[][4],
|
||||
dst[i*4+3] = FLOAT_TO_INT(rgba[i][RCOMP]);
|
||||
}
|
||||
break;
|
||||
case GL_DUDV_ATI:
|
||||
case GL_DU8DV8_ATI:
|
||||
for (i=0;i<n;i++) {
|
||||
dst[i*2+0] = FLOAT_TO_INT(rgba[i][RCOMP]);
|
||||
dst[i*2+1] = FLOAT_TO_INT(rgba[i][GCOMP]);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
_mesa_problem(ctx, "bad format in _mesa_pack_rgba_span\n");
|
||||
}
|
||||
@@ -2212,6 +2281,13 @@ _mesa_pack_rgba_span_float(GLcontext *ctx, GLuint n, GLfloat rgba[][4],
|
||||
dst[i*4+3] = rgba[i][RCOMP];
|
||||
}
|
||||
break;
|
||||
case GL_DUDV_ATI:
|
||||
case GL_DU8DV8_ATI:
|
||||
for (i=0;i<n;i++) {
|
||||
dst[i*2+0] = rgba[i][RCOMP];
|
||||
dst[i*2+1] = rgba[i][GCOMP];
|
||||
}
|
||||
break;
|
||||
default:
|
||||
_mesa_problem(ctx, "bad format in _mesa_pack_rgba_span\n");
|
||||
}
|
||||
@@ -2285,6 +2361,13 @@ _mesa_pack_rgba_span_float(GLcontext *ctx, GLuint n, GLfloat rgba[][4],
|
||||
dst[i*4+3] = _mesa_float_to_half(rgba[i][RCOMP]);
|
||||
}
|
||||
break;
|
||||
case GL_DUDV_ATI:
|
||||
case GL_DU8DV8_ATI:
|
||||
for (i=0;i<n;i++) {
|
||||
dst[i*2+0] = _mesa_float_to_half(rgba[i][RCOMP]);
|
||||
dst[i*2+1] = _mesa_float_to_half(rgba[i][GCOMP]);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
_mesa_problem(ctx, "bad format in _mesa_pack_rgba_span\n");
|
||||
}
|
||||
@@ -2834,7 +2917,8 @@ extract_float_rgba(GLuint n, GLfloat rgba[][4],
|
||||
srcFormat == GL_BGR ||
|
||||
srcFormat == GL_RGBA ||
|
||||
srcFormat == GL_BGRA ||
|
||||
srcFormat == GL_ABGR_EXT);
|
||||
srcFormat == GL_ABGR_EXT ||
|
||||
srcFormat == GL_DUDV_ATI);
|
||||
|
||||
ASSERT(srcType == GL_UNSIGNED_BYTE ||
|
||||
srcType == GL_BYTE ||
|
||||
@@ -2949,6 +3033,13 @@ extract_float_rgba(GLuint n, GLfloat rgba[][4],
|
||||
aComp = 0;
|
||||
stride = 4;
|
||||
break;
|
||||
case GL_DUDV_ATI:
|
||||
redIndex = 0;
|
||||
greenIndex = 1;
|
||||
blueIndex = -1;
|
||||
alphaIndex = -1;
|
||||
stride = 2;
|
||||
break;
|
||||
default:
|
||||
_mesa_problem(NULL, "bad srcFormat in extract float data");
|
||||
return;
|
||||
@@ -3877,6 +3968,62 @@ _mesa_unpack_color_span_float( GLcontext *ctx,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Similar to _mesa_unpack_color_span_float(), but for dudv data instead of rgba,
|
||||
* directly return GLbyte data, no transfer ops apply.
|
||||
*/
|
||||
void
|
||||
_mesa_unpack_dudv_span_byte( GLcontext *ctx,
|
||||
GLuint n, GLenum dstFormat, GLbyte dest[],
|
||||
GLenum srcFormat, GLenum srcType,
|
||||
const GLvoid *source,
|
||||
const struct gl_pixelstore_attrib *srcPacking,
|
||||
GLbitfield transferOps )
|
||||
{
|
||||
ASSERT(dstFormat == GL_DUDV_ATI);
|
||||
ASSERT(srcFormat == GL_DUDV_ATI);
|
||||
|
||||
ASSERT(srcType == GL_UNSIGNED_BYTE ||
|
||||
srcType == GL_BYTE ||
|
||||
srcType == GL_UNSIGNED_SHORT ||
|
||||
srcType == GL_SHORT ||
|
||||
srcType == GL_UNSIGNED_INT ||
|
||||
srcType == GL_INT ||
|
||||
srcType == GL_HALF_FLOAT_ARB ||
|
||||
srcType == GL_FLOAT);
|
||||
|
||||
/* general solution */
|
||||
{
|
||||
GLint dstComponents;
|
||||
GLfloat rgba[MAX_WIDTH][4];
|
||||
|
||||
dstComponents = _mesa_components_in_format( dstFormat );
|
||||
/* source & dest image formats should have been error checked by now */
|
||||
assert(dstComponents > 0);
|
||||
|
||||
/*
|
||||
* Extract image data and convert to RGBA floats
|
||||
*/
|
||||
assert(n <= MAX_WIDTH);
|
||||
extract_float_rgba(n, rgba, srcFormat, srcType, source,
|
||||
srcPacking->SwapBytes);
|
||||
|
||||
|
||||
/* Now determine which color channels we need to produce.
|
||||
* And determine the dest index (offset) within each color tuple.
|
||||
*/
|
||||
|
||||
/* Now pack results in the requested dstFormat */
|
||||
GLbyte *dst = dest;
|
||||
GLuint i;
|
||||
for (i = 0; i < n; i++) {
|
||||
/* not sure - need clamp[-1,1] here? */
|
||||
dst[0] = FLOAT_TO_BYTE(rgba[i][RCOMP]);
|
||||
dst[1] = FLOAT_TO_BYTE(rgba[i][GCOMP]);
|
||||
dst += dstComponents;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Unpack a row of color index data from a client buffer according to
|
||||
|
@@ -198,6 +198,13 @@ _mesa_unpack_color_span_float( GLcontext *ctx,
|
||||
const struct gl_pixelstore_attrib *srcPacking,
|
||||
GLbitfield transferOps );
|
||||
|
||||
extern void
|
||||
_mesa_unpack_dudv_span_byte( GLcontext *ctx,
|
||||
GLuint n, GLenum dstFormat, GLbyte dest[],
|
||||
GLenum srcFormat, GLenum srcType,
|
||||
const GLvoid *source,
|
||||
const struct gl_pixelstore_attrib *srcPacking,
|
||||
GLbitfield transferOps );
|
||||
|
||||
extern void
|
||||
_mesa_unpack_index_span( const GLcontext *ctx, GLuint n,
|
||||
|
@@ -54,13 +54,16 @@ extern GLfloat _mesa_ubyte_to_float_color_tab[256];
|
||||
#define FLOAT_TO_BYTE(X) ( (((GLint) (255.0F * (X))) - 1) / 2 )
|
||||
|
||||
|
||||
/** Convert GLushort in [0,65536] to GLfloat in [0.0,1.0] */
|
||||
/** Convert GLushort in [0,65535] to GLfloat in [0.0,1.0] */
|
||||
#define USHORT_TO_FLOAT(S) ((GLfloat) (S) * (1.0F / 65535.0F))
|
||||
|
||||
/** Convert GLfloat in [0.0,1.0] to GLushort in [0, 65535] */
|
||||
#define FLOAT_TO_USHORT(X) ((GLuint) ((X) * 65535.0))
|
||||
|
||||
/** Convert GLshort in [-32768,32767] to GLfloat in [-1.0,1.0] */
|
||||
#define SHORT_TO_FLOAT(S) ((2.0F * (S) + 1.0F) * (1.0F/65535.0F))
|
||||
|
||||
/** Convert GLfloat in [0.0,1.0] to GLshort in [-32768,32767] */
|
||||
/** Convert GLfloat in [-1.0,1.0] to GLshort in [-32768,32767] */
|
||||
#define FLOAT_TO_SHORT(X) ( (((GLint) (65535.0F * (X))) - 1) / 2 )
|
||||
|
||||
|
||||
|
@@ -226,7 +226,6 @@ do_row(GLenum datatype, GLuint comps, GLint srcWidth,
|
||||
dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) / 4;
|
||||
}
|
||||
}
|
||||
|
||||
else if (datatype == GL_FLOAT && comps == 4) {
|
||||
GLuint i, j, k;
|
||||
const GLfloat(*rowA)[4] = (const GLfloat(*)[4]) srcRowA;
|
||||
@@ -471,6 +470,17 @@ do_row(GLenum datatype, GLuint comps, GLint srcWidth,
|
||||
dst[i] = (blue << 5) | (green << 2) | red;
|
||||
}
|
||||
}
|
||||
else if (datatype == GL_BYTE && comps == 2) {
|
||||
GLuint i, j, k;
|
||||
const GLbyte(*rowA)[2] = (const GLbyte(*)[2]) srcRowA;
|
||||
const GLbyte(*rowB)[2] = (const GLbyte(*)[2]) srcRowB;
|
||||
GLbyte(*dst)[2] = (GLbyte(*)[2]) dstRow;
|
||||
for (i = j = 0, k = k0; i < (GLuint) dstWidth;
|
||||
i++, j += colStride, k += colStride) {
|
||||
dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) >> 2;
|
||||
dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) >> 2;
|
||||
}
|
||||
}
|
||||
else {
|
||||
_mesa_problem(NULL, "bad format in do_row()");
|
||||
}
|
||||
|
@@ -1390,6 +1390,8 @@ struct gl_texture_unit
|
||||
GLbitfield _GenFlags; /**< Bitwise-OR of Gen[STRQ]._ModeBit */
|
||||
|
||||
GLfloat LodBias; /**< for biasing mipmap levels */
|
||||
GLenum BumpTarget;
|
||||
GLfloat RotMatrix[4]; /* 2x2 matrix */
|
||||
|
||||
/**
|
||||
* \name GL_EXT_texture_env_combine
|
||||
@@ -2388,6 +2390,8 @@ struct gl_constants
|
||||
GLuint MaxSamples; /**< GL_ARB_framebuffer_object */
|
||||
|
||||
GLuint MaxVarying; /**< Number of float[4] varying parameters */
|
||||
|
||||
GLbitfield SupportedBumpUnits; /**> units supporting GL_ATI_envmap_bumpmap as targets */
|
||||
};
|
||||
|
||||
|
||||
@@ -2484,6 +2488,7 @@ struct gl_extensions
|
||||
GLboolean APPLE_client_storage;
|
||||
GLboolean APPLE_packed_pixels;
|
||||
GLboolean APPLE_vertex_array_object;
|
||||
GLboolean ATI_envmap_bumpmap;
|
||||
GLboolean ATI_texture_mirror_once;
|
||||
GLboolean ATI_texture_env_combine3;
|
||||
GLboolean ATI_fragment_shader;
|
||||
|
@@ -144,6 +144,10 @@ set_combiner_mode(GLcontext *ctx,
|
||||
case GL_MODULATE_SUBTRACT_ATI:
|
||||
legal = ctx->Extensions.ATI_texture_env_combine3;
|
||||
break;
|
||||
case GL_BUMP_ENVMAP_ATI:
|
||||
legal = (ctx->Extensions.ATI_envmap_bumpmap &&
|
||||
pname == GL_COMBINE_RGB);
|
||||
break;
|
||||
default:
|
||||
legal = GL_FALSE;
|
||||
}
|
||||
@@ -500,6 +504,26 @@ _mesa_TexEnvfv( GLenum target, GLenum pname, const GLfloat *param )
|
||||
case GL_ALPHA_SCALE:
|
||||
set_combiner_scale(ctx, texUnit, pname, param[0]);
|
||||
break;
|
||||
case GL_BUMP_TARGET_ATI:
|
||||
if (!ctx->Extensions.ATI_envmap_bumpmap) {
|
||||
_mesa_error( ctx, GL_INVALID_ENUM, "glTexEnv(pname=0x%x)", pname );
|
||||
return;
|
||||
}
|
||||
if (((GLenum) (GLint) param[0] < GL_TEXTURE0) ||
|
||||
((GLenum) (GLint) param[0] > GL_TEXTURE31)) {
|
||||
/* spec doesn't say this but it seems logical */
|
||||
_mesa_error( ctx, GL_INVALID_ENUM, "glTexEnv(param=0x%x)", (GLenum) (GLint) param[0]);
|
||||
return;
|
||||
}
|
||||
if (!((1 << ((GLenum) (GLint) param[0] - GL_TEXTURE0)) & ctx->Const.SupportedBumpUnits)) {
|
||||
_mesa_error( ctx, GL_INVALID_VALUE, "glTexEnv(param=0x%x)", (GLenum) (GLint) param[0]);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
FLUSH_VERTICES(ctx, _NEW_TEXTURE);
|
||||
texUnit->BumpTarget = (GLenum) (GLint) param[0];
|
||||
}
|
||||
break;
|
||||
default:
|
||||
_mesa_error( ctx, GL_INVALID_ENUM, "glTexEnv(pname)" );
|
||||
return;
|
||||
@@ -735,6 +759,16 @@ get_texenvi(GLcontext *ctx, const struct gl_texture_unit *texUnit,
|
||||
_mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
|
||||
}
|
||||
break;
|
||||
case GL_BUMP_TARGET_ATI:
|
||||
/* spec doesn't say so, but I think this should be queryable */
|
||||
if (ctx->Extensions.ATI_envmap_bumpmap) {
|
||||
return texUnit->BumpTarget;
|
||||
}
|
||||
else {
|
||||
_mesa_error(ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)");
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
;
|
||||
}
|
||||
@@ -874,4 +908,142 @@ _mesa_GetTexEnviv( GLenum target, GLenum pname, GLint *params )
|
||||
}
|
||||
}
|
||||
|
||||
/* why does ATI_envmap_bumpmap require new entrypoints? Should just
|
||||
reuse TexEnv ones... */
|
||||
void GLAPIENTRY
|
||||
_mesa_TexBumpParameterivATI( GLenum pname, const GLint *param )
|
||||
{
|
||||
GLfloat p[4];
|
||||
if (pname == GL_BUMP_ROT_MATRIX_ATI) {
|
||||
/* hope that conversion is correct here */
|
||||
p[0] = INT_TO_FLOAT( param[0] );
|
||||
p[1] = INT_TO_FLOAT( param[1] );
|
||||
p[2] = INT_TO_FLOAT( param[2] );
|
||||
p[3] = INT_TO_FLOAT( param[3] );
|
||||
}
|
||||
else {
|
||||
p[0] = (GLfloat) param[0];
|
||||
p[1] = p[2] = p[3] = 0; /* init to zero, just to be safe */
|
||||
}
|
||||
_mesa_TexBumpParameterfvATI( pname, p );
|
||||
}
|
||||
|
||||
void GLAPIENTRY
|
||||
_mesa_TexBumpParameterfvATI( GLenum pname, const GLfloat *param )
|
||||
{
|
||||
struct gl_texture_unit *texUnit;
|
||||
GET_CURRENT_CONTEXT(ctx);
|
||||
ASSERT_OUTSIDE_BEGIN_END(ctx);
|
||||
|
||||
/* should return error if extension not supported? */
|
||||
texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
|
||||
|
||||
if (pname == GL_BUMP_ROT_MATRIX_ATI) {
|
||||
if (TEST_EQ_4V(param, texUnit->RotMatrix))
|
||||
return;
|
||||
FLUSH_VERTICES(ctx, _NEW_TEXTURE);
|
||||
COPY_4FV(texUnit->RotMatrix, param);
|
||||
}
|
||||
else {
|
||||
_mesa_error( ctx, GL_INVALID_ENUM, "glTexBumpParameter(pname)" );
|
||||
return;
|
||||
}
|
||||
/* Drivers might want to know about this, instead of dedicated function
|
||||
just shove it into TexEnv where it really belongs anyway */
|
||||
if (ctx->Driver.TexEnv) {
|
||||
(*ctx->Driver.TexEnv)( ctx, 0, pname, param );
|
||||
}
|
||||
}
|
||||
|
||||
void GLAPIENTRY
|
||||
_mesa_GetTexBumpParameterivATI( GLenum pname, GLint *param )
|
||||
{
|
||||
const struct gl_texture_unit *texUnit;
|
||||
GLint i;
|
||||
GLint temp = 0;
|
||||
GET_CURRENT_CONTEXT(ctx);
|
||||
ASSERT_OUTSIDE_BEGIN_END(ctx);
|
||||
|
||||
/* should return error if extension not supported? */
|
||||
texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
|
||||
|
||||
if (pname == GL_BUMP_ROT_MATRIX_SIZE_ATI) {
|
||||
/* spec leaves open to support larger matrices.
|
||||
Don't think anyone would ever want to use it
|
||||
(and apps almost certainly would not understand it and
|
||||
thus fail to submit matrices correctly) so hardcode this. */
|
||||
*param = 4;
|
||||
}
|
||||
else if (pname == GL_BUMP_ROT_MATRIX_ATI) {
|
||||
/* hope that conversion is correct here */
|
||||
param[0] = FLOAT_TO_INT(texUnit->RotMatrix[0]);
|
||||
param[1] = FLOAT_TO_INT(texUnit->RotMatrix[1]);
|
||||
param[2] = FLOAT_TO_INT(texUnit->RotMatrix[2]);
|
||||
param[3] = FLOAT_TO_INT(texUnit->RotMatrix[3]);
|
||||
}
|
||||
else if (pname == GL_BUMP_NUM_TEX_UNITS_ATI) {
|
||||
for (i = 0; i < ctx->Const.MaxTextureImageUnits; i++) {
|
||||
if (ctx->Const.SupportedBumpUnits & (1 << i)) {
|
||||
temp++;
|
||||
}
|
||||
}
|
||||
*param = temp;
|
||||
}
|
||||
else if (pname == GL_BUMP_TEX_UNITS_ATI) {
|
||||
for (i = 0; i < ctx->Const.MaxTextureImageUnits; i++) {
|
||||
if (ctx->Const.SupportedBumpUnits & (1 << i)) {
|
||||
*param++ = i + GL_TEXTURE0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
_mesa_error( ctx, GL_INVALID_ENUM, "glGetTexBumpParameter(pname)" );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void GLAPIENTRY
|
||||
_mesa_GetTexBumpParameterfvATI( GLenum pname, GLfloat *param )
|
||||
{
|
||||
const struct gl_texture_unit *texUnit;
|
||||
GLint i;
|
||||
GLint temp = 0;
|
||||
GET_CURRENT_CONTEXT(ctx);
|
||||
ASSERT_OUTSIDE_BEGIN_END(ctx);
|
||||
|
||||
/* should return error if extension not supported? */
|
||||
texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
|
||||
|
||||
if (pname == GL_BUMP_ROT_MATRIX_SIZE_ATI) {
|
||||
/* spec leaves open to support larger matrices.
|
||||
Don't think anyone would ever want to use it
|
||||
(and apps might not understand it) so hardcode this. */
|
||||
*param = (GLfloat) 4;
|
||||
}
|
||||
else if (pname == GL_BUMP_ROT_MATRIX_ATI) {
|
||||
param[0] = texUnit->RotMatrix[0];
|
||||
param[1] = texUnit->RotMatrix[1];
|
||||
param[2] = texUnit->RotMatrix[2];
|
||||
param[3] = texUnit->RotMatrix[3];
|
||||
}
|
||||
else if (pname == GL_BUMP_NUM_TEX_UNITS_ATI) {
|
||||
for (i = 0; i < ctx->Const.MaxTextureImageUnits; i++) {
|
||||
if (ctx->Const.SupportedBumpUnits & (1 << i)) {
|
||||
temp++;
|
||||
}
|
||||
}
|
||||
*param = (GLfloat) temp;
|
||||
}
|
||||
else if (pname == GL_BUMP_TEX_UNITS_ATI) {
|
||||
for (i = 0; i < ctx->Const.MaxTextureImageUnits; i++) {
|
||||
if (ctx->Const.SupportedBumpUnits & (1 << i)) {
|
||||
*param++ = (GLfloat) (i + GL_TEXTURE0);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
_mesa_error( ctx, GL_INVALID_ENUM, "glGetTexBumpParameter(pname)" );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -48,5 +48,16 @@ _mesa_TexEnvi( GLenum target, GLenum pname, GLint param );
|
||||
extern void GLAPIENTRY
|
||||
_mesa_TexEnviv( GLenum target, GLenum pname, const GLint *param );
|
||||
|
||||
extern void GLAPIENTRY
|
||||
_mesa_TexBumpParameterivATI( GLenum pname, const GLint *param );
|
||||
|
||||
extern void GLAPIENTRY
|
||||
_mesa_TexBumpParameterfvATI( GLenum pname, const GLfloat *param );
|
||||
|
||||
extern void GLAPIENTRY
|
||||
_mesa_GetTexBumpParameterivATI( GLenum pname, GLint *param );
|
||||
|
||||
extern void GLAPIENTRY
|
||||
_mesa_GetTexBumpParameterfvATI( GLenum pname, GLfloat *param );
|
||||
|
||||
#endif /* TEXENV_H */
|
||||
|
@@ -94,11 +94,11 @@ struct state_key {
|
||||
GLuint ScaleShiftA:2;
|
||||
|
||||
GLuint NumArgsRGB:3;
|
||||
GLuint ModeRGB:4;
|
||||
GLuint ModeRGB:5;
|
||||
struct mode_opt OptRGB[MAX_TERMS];
|
||||
|
||||
GLuint NumArgsA:3;
|
||||
GLuint ModeA:4;
|
||||
GLuint ModeA:5;
|
||||
struct mode_opt OptA[MAX_TERMS];
|
||||
} unit[8];
|
||||
};
|
||||
@@ -194,7 +194,8 @@ static GLuint translate_source( GLenum src )
|
||||
#define MODE_MODULATE_SUBTRACT_ATI 12 /* r = a0 * a2 - a1 */
|
||||
#define MODE_ADD_PRODUCTS 13 /* r = a0 * a1 + a2 * a3 */
|
||||
#define MODE_ADD_PRODUCTS_SIGNED 14 /* r = a0 * a1 + a2 * a3 - 0.5 */
|
||||
#define MODE_UNKNOWN 15
|
||||
#define MODE_BUMP_ENVMAP_ATI 15 /* special */
|
||||
#define MODE_UNKNOWN 16
|
||||
|
||||
/**
|
||||
* Translate GL combiner state into a MODE_x value
|
||||
@@ -223,6 +224,7 @@ static GLuint translate_mode( GLenum envMode, GLenum mode )
|
||||
case GL_MODULATE_ADD_ATI: return MODE_MODULATE_ADD_ATI;
|
||||
case GL_MODULATE_SIGNED_ADD_ATI: return MODE_MODULATE_SIGNED_ADD_ATI;
|
||||
case GL_MODULATE_SUBTRACT_ATI: return MODE_MODULATE_SUBTRACT_ATI;
|
||||
case GL_BUMP_ENVMAP_ATI: return MODE_BUMP_ENVMAP_ATI;
|
||||
default:
|
||||
assert(0);
|
||||
return MODE_UNKNOWN;
|
||||
@@ -397,6 +399,16 @@ static void make_state_key( GLcontext *ctx, struct state_key *key )
|
||||
key->unit[i].OptA[j].Source =
|
||||
translate_source(texUnit->_CurrentCombine->SourceA[j]);
|
||||
}
|
||||
|
||||
if (key->unit[i].ModeRGB == MODE_BUMP_ENVMAP_ATI) {
|
||||
/* requires some special translation */
|
||||
key->unit[i].NumArgsRGB = 2;
|
||||
key->unit[i].ScaleShiftRGB = 0;
|
||||
key->unit[i].OptRGB[0].Operand = OPR_SRC_COLOR;
|
||||
key->unit[i].OptRGB[0].Source = SRC_TEXTURE;
|
||||
key->unit[i].OptRGB[1].Operand = OPR_SRC_COLOR;
|
||||
key->unit[i].OptRGB[1].Source = texUnit->BumpTarget - GL_TEXTURE0 + SRC_TEXTURE0;
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) {
|
||||
@@ -464,6 +476,11 @@ struct texenv_fragment_program {
|
||||
* else undef.
|
||||
*/
|
||||
|
||||
struct ureg texcoord_tex[MAX_TEXTURE_COORD_UNITS];
|
||||
/* Reg containing texcoord for a texture unit,
|
||||
* needed for bump mapping, else undef.
|
||||
*/
|
||||
|
||||
struct ureg src_previous; /**< Reg containing color from previous
|
||||
* stage. May need to be decl'd.
|
||||
*/
|
||||
@@ -756,6 +773,7 @@ static struct ureg emit_texld( struct texenv_fragment_program *p,
|
||||
*/
|
||||
reserve_temp(p, dest);
|
||||
|
||||
#if 0
|
||||
/* Is this a texture indirection?
|
||||
*/
|
||||
if ((coord.file == PROGRAM_TEMPORARY &&
|
||||
@@ -767,6 +785,7 @@ static struct ureg emit_texld( struct texenv_fragment_program *p,
|
||||
p->alu_temps = 0;
|
||||
assert(0); /* KW: texture env crossbar */
|
||||
}
|
||||
#endif
|
||||
|
||||
return dest;
|
||||
}
|
||||
@@ -1052,6 +1071,10 @@ static struct ureg emit_combine( struct texenv_fragment_program *p,
|
||||
emit_arith( p, OPCODE_SUB, dest, mask, saturate, tmp0, half, undef );
|
||||
}
|
||||
return dest;
|
||||
case MODE_BUMP_ENVMAP_ATI:
|
||||
/* special - not handled here */
|
||||
assert(0);
|
||||
return src[0];
|
||||
default:
|
||||
assert(0);
|
||||
return src[0];
|
||||
@@ -1074,6 +1097,10 @@ emit_texenv(struct texenv_fragment_program *p, GLuint unit)
|
||||
if (!key->unit[unit].enabled) {
|
||||
return get_source(p, SRC_PREVIOUS, 0);
|
||||
}
|
||||
if (key->unit[unit].ModeRGB == MODE_BUMP_ENVMAP_ATI) {
|
||||
/* this isn't really a env stage delivering a color and handled elsewhere */
|
||||
return get_source(p, SRC_PREVIOUS, 0);
|
||||
}
|
||||
|
||||
switch (key->unit[unit].ModeRGB) {
|
||||
case MODE_DOT3_RGB_EXT:
|
||||
@@ -1163,9 +1190,17 @@ static void load_texture( struct texenv_fragment_program *p, GLuint unit )
|
||||
{
|
||||
if (is_undef(p->src_texture[unit])) {
|
||||
GLuint texTarget = p->state->unit[unit].source_index;
|
||||
struct ureg texcoord = register_input(p, FRAG_ATTRIB_TEX0+unit);
|
||||
struct ureg texcoord;
|
||||
struct ureg tmp = get_tex_temp( p );
|
||||
|
||||
if (is_undef(p->texcoord_tex[unit])) {
|
||||
texcoord = register_input(p, FRAG_ATTRIB_TEX0+unit);
|
||||
}
|
||||
else {
|
||||
/* might want to reuse this reg for tex output actually */
|
||||
texcoord = p->texcoord_tex[unit];
|
||||
}
|
||||
|
||||
if (texTarget == TEXTURE_UNKNOWN_INDEX)
|
||||
program_error(p, "TexSrcBit");
|
||||
|
||||
@@ -1243,6 +1278,40 @@ load_texunit_sources( struct texenv_fragment_program *p, int unit )
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate instructions for loading bump map textures.
|
||||
*/
|
||||
static GLboolean
|
||||
load_texunit_bumpmap( struct texenv_fragment_program *p, int unit )
|
||||
{
|
||||
struct state_key *key = p->state;
|
||||
GLuint bumpedUnitNr = key->unit[unit].OptRGB[1].Source - SRC_TEXTURE0;
|
||||
struct ureg texcDst, bumpMapRes;
|
||||
struct ureg constdudvcolor = register_const4f(p, 0.0, 0.0, 0.0, 1.0);
|
||||
struct ureg texcSrc = register_input(p, FRAG_ATTRIB_TEX0 + bumpedUnitNr);
|
||||
struct ureg rotMat0 = register_param3( p, STATE_INTERNAL, STATE_ROT_MATRIX_0, unit );
|
||||
struct ureg rotMat1 = register_param3( p, STATE_INTERNAL, STATE_ROT_MATRIX_1, unit );
|
||||
|
||||
load_texenv_source( p, unit + SRC_TEXTURE0, unit );
|
||||
|
||||
bumpMapRes = get_source(p, key->unit[unit].OptRGB[0].Source, unit);
|
||||
texcDst = get_tex_temp( p );
|
||||
p->texcoord_tex[bumpedUnitNr] = texcDst;
|
||||
|
||||
/* apply rot matrix and add coords to be available in next phase */
|
||||
/* dest = (Arg0.xxxx * rotMat0 + Arg1) + (Arg0.yyyy * rotMat1) */
|
||||
/* note only 2 coords are affected the rest are left unchanged (mul by 0) */
|
||||
emit_arith( p, OPCODE_MAD, texcDst, WRITEMASK_XYZW, 0,
|
||||
swizzle1(bumpMapRes, SWIZZLE_X), rotMat0, texcSrc );
|
||||
emit_arith( p, OPCODE_MAD, texcDst, WRITEMASK_XYZW, 0,
|
||||
swizzle1(bumpMapRes, SWIZZLE_Y), rotMat1, texcDst );
|
||||
|
||||
/* move 0,0,0,1 into bumpmap src if someone (crossbar) is foolish
|
||||
enough to access this later, should optimize away */
|
||||
emit_arith( p, OPCODE_MOV, bumpMapRes, WRITEMASK_XYZW, 0, constdudvcolor, undef, undef );
|
||||
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a new fragment program which implements the context's
|
||||
@@ -1267,7 +1336,7 @@ create_new_program(GLcontext *ctx, struct state_key *key,
|
||||
*/
|
||||
p.program->Base.Instructions = instBuffer;
|
||||
p.program->Base.Target = GL_FRAGMENT_PROGRAM_ARB;
|
||||
p.program->Base.NumTexIndirections = 1; /* correct? */
|
||||
p.program->Base.NumTexIndirections = 1;
|
||||
p.program->Base.NumTexInstructions = 0;
|
||||
p.program->Base.NumAluInstructions = 0;
|
||||
p.program->Base.String = NULL;
|
||||
@@ -1280,8 +1349,10 @@ create_new_program(GLcontext *ctx, struct state_key *key,
|
||||
p.program->Base.InputsRead = 0;
|
||||
p.program->Base.OutputsWritten = 1 << FRAG_RESULT_COLOR;
|
||||
|
||||
for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++)
|
||||
for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
|
||||
p.src_texture[unit] = undef;
|
||||
p.texcoord_tex[unit] = undef;
|
||||
}
|
||||
|
||||
p.src_previous = undef;
|
||||
p.half = undef;
|
||||
@@ -1292,6 +1363,16 @@ create_new_program(GLcontext *ctx, struct state_key *key,
|
||||
release_temps(ctx, &p);
|
||||
|
||||
if (key->enabled_units) {
|
||||
GLboolean needbumpstage = GL_FALSE;
|
||||
/* Zeroth pass - bump map textures first */
|
||||
for (unit = 0 ; unit < ctx->Const.MaxTextureUnits ; unit++)
|
||||
if (key->unit[unit].enabled && key->unit[unit].ModeRGB == MODE_BUMP_ENVMAP_ATI) {
|
||||
needbumpstage = GL_TRUE;
|
||||
load_texunit_bumpmap( &p, unit );
|
||||
}
|
||||
if (needbumpstage)
|
||||
p.program->Base.NumTexIndirections++;
|
||||
|
||||
/* First pass - to support texture_env_crossbar, first identify
|
||||
* all referenced texture sources and emit texld instructions
|
||||
* for each:
|
||||
|
@@ -696,6 +696,33 @@ const struct gl_texture_format _mesa_texformat_intensity_float16 = {
|
||||
store_texel_intensity_f16 /* StoreTexel */
|
||||
};
|
||||
|
||||
const struct gl_texture_format _mesa_texformat_dudv8 = {
|
||||
MESA_FORMAT_DUDV8, /* MesaFormat */
|
||||
GL_DUDV_ATI, /* BaseFormat */
|
||||
/* FIXME: spec doesn't say since that parameter didn't exist then,
|
||||
but this should be something like SIGNED_NORMALIZED */
|
||||
GL_UNSIGNED_NORMALIZED_ARB, /* DataType */
|
||||
/* maybe should add dudvBits field, but spec seems to be
|
||||
lacking the ability to query with GetTexLevelParameter anyway */
|
||||
0, /* RedBits */
|
||||
0, /* GreenBits */
|
||||
0, /* BlueBits */
|
||||
0, /* AlphaBits */
|
||||
0, /* LuminanceBits */
|
||||
0, /* IntensityBits */
|
||||
0, /* IndexBits */
|
||||
0, /* DepthBits */
|
||||
0, /* StencilBits */
|
||||
2, /* TexelBytes */
|
||||
_mesa_texstore_dudv8, /* StoreTexImageFunc */
|
||||
NULL, /* FetchTexel1D */
|
||||
NULL, /* FetchTexel2D */
|
||||
NULL, /* FetchTexel3D */
|
||||
NULL, /* FetchTexel1Df */
|
||||
fetch_texel_2d_dudv8, /* FetchTexel2Df */
|
||||
NULL, /* FetchTexel3Df */
|
||||
NULL /* StoreTexel */
|
||||
};
|
||||
|
||||
/*@}*/
|
||||
|
||||
@@ -1634,6 +1661,16 @@ _mesa_choose_tex_format( GLcontext *ctx, GLint internalFormat,
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx->Extensions.ATI_envmap_bumpmap) {
|
||||
switch (internalFormat) {
|
||||
case GL_DUDV_ATI:
|
||||
case GL_DU8DV8_ATI:
|
||||
return &_mesa_texformat_dudv8;
|
||||
default:
|
||||
; /* fallthrough */
|
||||
}
|
||||
}
|
||||
|
||||
#if FEATURE_EXT_texture_sRGB
|
||||
if (ctx->Extensions.EXT_texture_sRGB) {
|
||||
switch (internalFormat) {
|
||||
@@ -1778,6 +1815,11 @@ _mesa_format_to_type_and_comps(const struct gl_texture_format *format,
|
||||
*comps = 1;
|
||||
return;
|
||||
|
||||
case MESA_FORMAT_DUDV8:
|
||||
*datatype = GL_BYTE;
|
||||
*comps = 2;
|
||||
return;
|
||||
|
||||
#if FEATURE_EXT_texture_sRGB
|
||||
case MESA_FORMAT_SRGB8:
|
||||
*datatype = GL_UNSIGNED_BYTE;
|
||||
|
@@ -161,7 +161,14 @@ enum _format {
|
||||
MESA_FORMAT_LUMINANCE_ALPHA_FLOAT32,
|
||||
MESA_FORMAT_LUMINANCE_ALPHA_FLOAT16,
|
||||
MESA_FORMAT_INTENSITY_FLOAT32,
|
||||
MESA_FORMAT_INTENSITY_FLOAT16
|
||||
MESA_FORMAT_INTENSITY_FLOAT16,
|
||||
/*@}*/
|
||||
|
||||
/**
|
||||
* \name Signed fixed point texture formats.
|
||||
*/
|
||||
/*@{*/
|
||||
MESA_FORMAT_DUDV8
|
||||
/*@}*/
|
||||
};
|
||||
|
||||
@@ -209,6 +216,11 @@ extern const struct gl_texture_format _mesa_texformat_intensity_float32;
|
||||
extern const struct gl_texture_format _mesa_texformat_intensity_float16;
|
||||
/*@}*/
|
||||
|
||||
/** Signed fixed point texture formats */
|
||||
/*@{*/
|
||||
extern const struct gl_texture_format _mesa_texformat_dudv8;
|
||||
/*@}*/
|
||||
|
||||
/** \name Assorted hardware-friendly formats */
|
||||
/*@{*/
|
||||
extern const struct gl_texture_format _mesa_texformat_rgba8888;
|
||||
|
@@ -1269,7 +1269,7 @@ static void FETCH(sl8)(const struct gl_texture_image *texImage,
|
||||
texel[RCOMP] =
|
||||
texel[GCOMP] =
|
||||
texel[BCOMP] = nonlinear_to_linear(src[0]);
|
||||
texel[ACOMP] = CHAN_MAX;
|
||||
texel[ACOMP] = 1.0F;
|
||||
}
|
||||
|
||||
#if DIM == 3
|
||||
@@ -1308,7 +1308,22 @@ static void store_texel_sla8(struct gl_texture_image *texImage,
|
||||
|
||||
#endif /* FEATURE_EXT_texture_sRGB */
|
||||
|
||||
#if DIM == 2
|
||||
/* MESA_FORMAT_DUDV8 ********************************************************/
|
||||
|
||||
/* this format by definition produces 0,0,0,1 as rgba values,
|
||||
however we'll return the dudv values as rg and fix up elsewhere */
|
||||
static void FETCH(dudv8)(const struct gl_texture_image *texImage,
|
||||
GLint i, GLint j, GLint k, GLfloat *texel )
|
||||
{
|
||||
const GLbyte *src = TEXEL_ADDR(GLbyte, texImage, i, j, k, 2);
|
||||
texel[RCOMP] = BYTE_TO_FLOAT(src[0]);
|
||||
texel[GCOMP] = BYTE_TO_FLOAT(src[1]);
|
||||
texel[BCOMP] = 0;
|
||||
texel[ACOMP] = 0;
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
/* MESA_FORMAT_YCBCR *********************************************************/
|
||||
|
||||
|
@@ -339,6 +339,17 @@ _mesa_base_tex_format( GLcontext *ctx, GLint internalFormat )
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx->Extensions.ATI_envmap_bumpmap) {
|
||||
switch (internalFormat) {
|
||||
case GL_DUDV_ATI:
|
||||
case GL_DU8DV8_ATI:
|
||||
return GL_DUDV_ATI;
|
||||
default:
|
||||
; /* fallthrough */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (ctx->Extensions.EXT_packed_depth_stencil) {
|
||||
switch (internalFormat) {
|
||||
case GL_DEPTH_STENCIL_EXT:
|
||||
@@ -568,6 +579,20 @@ is_depthstencil_format(GLenum format)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if the given image format is a dudv format.
|
||||
*/
|
||||
static GLboolean
|
||||
is_dudv_format(GLenum format)
|
||||
{
|
||||
switch (format) {
|
||||
case GL_DUDV_ATI:
|
||||
case GL_DU8DV8_ATI:
|
||||
return GL_TRUE;
|
||||
default:
|
||||
return GL_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
@@ -1539,7 +1564,8 @@ texture_error_check( GLcontext *ctx, GLenum target,
|
||||
(is_index_format(internalFormat) && !indexFormat) ||
|
||||
(is_depth_format(internalFormat) != is_depth_format(format)) ||
|
||||
(is_ycbcr_format(internalFormat) != is_ycbcr_format(format)) ||
|
||||
(is_depthstencil_format(internalFormat) != is_depthstencil_format(format))) {
|
||||
(is_depthstencil_format(internalFormat) != is_depthstencil_format(format)) ||
|
||||
(is_dudv_format(internalFormat) != is_dudv_format(format))) {
|
||||
if (!isProxy)
|
||||
_mesa_error(ctx, GL_INVALID_OPERATION,
|
||||
"glTexImage(internalFormat/format)");
|
||||
@@ -2273,6 +2299,12 @@ _mesa_GetTexImage( GLenum target, GLint level, GLenum format,
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ctx->Extensions.ATI_envmap_bumpmap
|
||||
&& is_dudv_format(format)) {
|
||||
_mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)");
|
||||
return;
|
||||
}
|
||||
|
||||
_mesa_lock_texture(ctx, texObj);
|
||||
{
|
||||
texImage = _mesa_select_tex_image(ctx, texObj, target, level);
|
||||
@@ -2313,6 +2345,11 @@ _mesa_GetTexImage( GLenum target, GLint level, GLenum format,
|
||||
_mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
|
||||
goto out;
|
||||
}
|
||||
else if (is_dudv_format(format)
|
||||
&& !is_dudv_format(texImage->TexFormat->BaseFormat)) {
|
||||
_mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (ctx->Pack.BufferObj->Name) {
|
||||
/* packing texture image into a PBO */
|
||||
|
@@ -95,6 +95,11 @@ _mesa_copy_texture_state( const GLcontext *src, GLcontext *dst )
|
||||
/* GL_EXT_texture_env_combine */
|
||||
dst->Texture.Unit[u].Combine = src->Texture.Unit[u].Combine;
|
||||
|
||||
/* GL_ATI_envmap_bumpmap - need this? */
|
||||
dst->Texture.Unit[u].BumpTarget = src->Texture.Unit[u].BumpTarget;
|
||||
COPY_4V(dst->Texture.Unit[u].RotMatrix, src->Texture.Unit[u].RotMatrix);
|
||||
|
||||
|
||||
/* copy texture object bindings, not contents of texture objects */
|
||||
_mesa_lock_context_textures(dst);
|
||||
|
||||
@@ -411,6 +416,10 @@ update_tex_combine(GLcontext *ctx, struct gl_texture_unit *texUnit)
|
||||
case GL_MODULATE_SUBTRACT_ATI:
|
||||
combine->_NumArgsRGB = 3;
|
||||
break;
|
||||
case GL_BUMP_ENVMAP_ATI:
|
||||
/* no real arguments for this case */
|
||||
combine->_NumArgsRGB = 0;
|
||||
break;
|
||||
default:
|
||||
combine->_NumArgsRGB = 0;
|
||||
_mesa_problem(ctx, "invalid RGB combine mode in update_texture_state");
|
||||
@@ -682,6 +691,7 @@ init_texture_unit( GLcontext *ctx, GLuint unit )
|
||||
texUnit->Combine = default_combine_state;
|
||||
texUnit->_EnvMode = default_combine_state;
|
||||
texUnit->_CurrentCombine = & texUnit->_EnvMode;
|
||||
texUnit->BumpTarget = GL_TEXTURE0;
|
||||
|
||||
texUnit->TexGenEnabled = 0x0;
|
||||
texUnit->GenS.Mode = GL_EYE_LINEAR;
|
||||
@@ -702,6 +712,16 @@ init_texture_unit( GLcontext *ctx, GLuint unit )
|
||||
ASSIGN_4V( texUnit->GenT.EyePlane, 0.0, 1.0, 0.0, 0.0 );
|
||||
ASSIGN_4V( texUnit->GenR.EyePlane, 0.0, 0.0, 0.0, 0.0 );
|
||||
ASSIGN_4V( texUnit->GenQ.EyePlane, 0.0, 0.0, 0.0, 0.0 );
|
||||
ASSIGN_4V( texUnit->GenS.ObjectPlane, 1.0, 0.0, 0.0, 0.0 );
|
||||
ASSIGN_4V( texUnit->GenT.ObjectPlane, 0.0, 1.0, 0.0, 0.0 );
|
||||
ASSIGN_4V( texUnit->GenR.ObjectPlane, 0.0, 0.0, 0.0, 0.0 );
|
||||
ASSIGN_4V( texUnit->GenQ.ObjectPlane, 0.0, 0.0, 0.0, 0.0 );
|
||||
ASSIGN_4V( texUnit->GenS.EyePlane, 1.0, 0.0, 0.0, 0.0 );
|
||||
ASSIGN_4V( texUnit->GenT.EyePlane, 0.0, 1.0, 0.0, 0.0 );
|
||||
ASSIGN_4V( texUnit->GenR.EyePlane, 0.0, 0.0, 0.0, 0.0 );
|
||||
ASSIGN_4V( texUnit->GenQ.EyePlane, 0.0, 0.0, 0.0, 0.0 );
|
||||
/* no mention of this in spec, but maybe id matrix expected? */
|
||||
ASSIGN_4V( texUnit->RotMatrix, 1.0, 0.0, 0.0, 1.0 );
|
||||
|
||||
/* initialize current texture object ptrs to the shared default objects */
|
||||
for (tex = 0; tex < NUM_TEXTURE_TARGETS; tex++) {
|
||||
|
@@ -2471,6 +2471,95 @@ _mesa_texstore_ycbcr(TEXSTORE_PARAMS)
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
GLboolean
|
||||
_mesa_texstore_dudv8(TEXSTORE_PARAMS)
|
||||
{
|
||||
const GLboolean littleEndian = _mesa_little_endian();
|
||||
|
||||
ASSERT(dstFormat == &_mesa_texformat_dudv8);
|
||||
ASSERT(dstFormat->TexelBytes == 2);
|
||||
ASSERT(ctx->Extensions.ATI_envmap_bumpmap);
|
||||
ASSERT((srcFormat == GL_DU8DV8_ATI) ||
|
||||
(srcFormat == GL_DUDV_ATI));
|
||||
ASSERT(baseInternalFormat == GL_DUDV_ATI);
|
||||
|
||||
if (!srcPacking->SwapBytes && srcType == GL_BYTE &&
|
||||
littleEndian) {
|
||||
/* simple memcpy path */
|
||||
memcpy_texture(ctx, dims,
|
||||
dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
|
||||
dstRowStride,
|
||||
dstImageOffsets,
|
||||
srcWidth, srcHeight, srcDepth, srcFormat, srcType,
|
||||
srcAddr, srcPacking);
|
||||
}
|
||||
else if (srcType == GL_BYTE) {
|
||||
|
||||
GLubyte dstmap[4];
|
||||
|
||||
/* dstmap - how to swizzle from RGBA to dst format:
|
||||
*/
|
||||
if (littleEndian) {
|
||||
dstmap[0] = 0;
|
||||
dstmap[1] = 3;
|
||||
}
|
||||
else {
|
||||
dstmap[0] = 3;
|
||||
dstmap[1] = 0;
|
||||
}
|
||||
dstmap[2] = ZERO; /* ? */
|
||||
dstmap[3] = ONE; /* ? */
|
||||
|
||||
_mesa_swizzle_ubyte_image(ctx, dims,
|
||||
GL_LUMINANCE_ALPHA, /* hack */
|
||||
GL_UNSIGNED_BYTE, /* hack */
|
||||
GL_LUMINANCE_ALPHA, /* hack */
|
||||
dstmap, 2,
|
||||
dstAddr, dstXoffset, dstYoffset, dstZoffset,
|
||||
dstRowStride, dstImageOffsets,
|
||||
srcWidth, srcHeight, srcDepth, srcAddr,
|
||||
srcPacking);
|
||||
}
|
||||
else {
|
||||
/* general path - note this is defined for 2d textures only */
|
||||
const GLint components = _mesa_components_in_format(baseInternalFormat);
|
||||
const GLint srcStride = _mesa_image_row_stride(srcPacking,
|
||||
srcWidth, srcFormat, srcType);
|
||||
GLbyte *tempImage, *dst, *src;
|
||||
GLint row;
|
||||
|
||||
tempImage = (GLbyte *) _mesa_malloc(srcWidth * srcHeight * srcDepth
|
||||
* components * sizeof(GLbyte));
|
||||
if (!tempImage)
|
||||
return GL_FALSE;
|
||||
|
||||
src = (GLbyte *) _mesa_image_address(dims, srcPacking, srcAddr,
|
||||
srcWidth, srcHeight,
|
||||
srcFormat, srcType,
|
||||
0, 0, 0);
|
||||
|
||||
dst = tempImage;
|
||||
for (row = 0; row < srcHeight; row++) {
|
||||
_mesa_unpack_dudv_span_byte(ctx, srcWidth, baseInternalFormat,
|
||||
dst, srcFormat, srcType, src,
|
||||
srcPacking, 0);
|
||||
dst += srcWidth * components;
|
||||
src += srcStride;
|
||||
}
|
||||
|
||||
src = tempImage;
|
||||
dst = (GLbyte *) dstAddr
|
||||
+ dstYoffset * dstRowStride
|
||||
+ dstXoffset * dstFormat->TexelBytes;
|
||||
for (row = 0; row < srcHeight; row++) {
|
||||
memcpy(dst, src, srcWidth * dstFormat->TexelBytes);
|
||||
dst += dstRowStride;
|
||||
src += srcWidth * dstFormat->TexelBytes;
|
||||
}
|
||||
_mesa_free((void *) tempImage);
|
||||
}
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
@@ -3882,7 +3971,7 @@ _mesa_get_teximage(GLcontext *ctx, GLenum target, GLint level,
|
||||
GLint col;
|
||||
GLbitfield transferOps = 0x0;
|
||||
|
||||
if (type == GL_FLOAT &&
|
||||
if (type == GL_FLOAT && texImage->TexFormat->BaseFormat != GL_DUDV_ATI &&
|
||||
((ctx->Color.ClampReadColor == GL_TRUE) ||
|
||||
(ctx->Color.ClampReadColor == GL_FIXED_ONLY_ARB &&
|
||||
texImage->TexFormat->DataType != GL_FLOAT)))
|
||||
|
@@ -78,7 +78,7 @@ extern GLboolean _mesa_texstore_sargb8(TEXSTORE_PARAMS);
|
||||
extern GLboolean _mesa_texstore_sl8(TEXSTORE_PARAMS);
|
||||
extern GLboolean _mesa_texstore_sla8(TEXSTORE_PARAMS);
|
||||
#endif
|
||||
|
||||
extern GLboolean _mesa_texstore_dudv8(TEXSTORE_PARAMS);
|
||||
|
||||
extern GLchan *
|
||||
_mesa_make_temp_chan_image(GLcontext *ctx, GLuint dims,
|
||||
|
@@ -506,6 +506,26 @@ _mesa_fetch_state(GLcontext *ctx, const gl_state_index state[],
|
||||
}
|
||||
}
|
||||
return;
|
||||
case STATE_ROT_MATRIX_0:
|
||||
{
|
||||
const int unit = (int) state[2];
|
||||
GLfloat *rotMat22 = ctx->Texture.Unit[unit].RotMatrix;
|
||||
value[0] = rotMat22[0];
|
||||
value[1] = rotMat22[2];
|
||||
value[2] = 0.0;
|
||||
value[3] = 0.0;
|
||||
}
|
||||
break;
|
||||
case STATE_ROT_MATRIX_1:
|
||||
{
|
||||
const int unit = (int) state[2];
|
||||
GLfloat *rotMat22 = ctx->Texture.Unit[unit].RotMatrix;
|
||||
value[0] = rotMat22[1];
|
||||
value[1] = rotMat22[3];
|
||||
value[2] = 0.0;
|
||||
value[3] = 0.0;
|
||||
}
|
||||
break;
|
||||
|
||||
/* XXX: make sure new tokens added here are also handled in the
|
||||
* _mesa_program_state_flags() switch, below.
|
||||
@@ -591,6 +611,8 @@ _mesa_program_state_flags(const gl_state_index state[STATE_LENGTH])
|
||||
|
||||
case STATE_TEXRECT_SCALE:
|
||||
case STATE_SHADOW_AMBIENT:
|
||||
case STATE_ROT_MATRIX_0:
|
||||
case STATE_ROT_MATRIX_1:
|
||||
return _NEW_TEXTURE;
|
||||
case STATE_FOG_PARAMS_OPTIMIZED:
|
||||
return _NEW_FOG;
|
||||
@@ -806,6 +828,12 @@ append_token(char *dst, gl_state_index k)
|
||||
case STATE_SHADOW_AMBIENT:
|
||||
append(dst, "CompareFailValue");
|
||||
break;
|
||||
case STATE_ROT_MATRIX_0:
|
||||
append(dst, "rotMatrixRow0");
|
||||
break;
|
||||
case STATE_ROT_MATRIX_1:
|
||||
append(dst, "rotMatrixRow1");
|
||||
break;
|
||||
default:
|
||||
/* probably STATE_INTERNAL_DRIVER+i (driver private state) */
|
||||
append(dst, "driverState");
|
||||
|
@@ -117,6 +117,8 @@ typedef enum gl_state_index_ {
|
||||
STATE_PCM_SCALE, /**< Post color matrix RGBA scale */
|
||||
STATE_PCM_BIAS, /**< Post color matrix RGBA bias */
|
||||
STATE_SHADOW_AMBIENT, /**< ARB_shadow_ambient fail value; token[2] is texture unit index */
|
||||
STATE_ROT_MATRIX_0, /**< ATI_envmap_bumpmap, rot matrix row 0 */
|
||||
STATE_ROT_MATRIX_1, /**< ATI_envmap_bumpmap, rot matrix row 1 */
|
||||
STATE_INTERNAL_DRIVER /* first available state index for drivers (must be last) */
|
||||
} gl_state_index;
|
||||
|
||||
|
@@ -591,6 +591,25 @@ texture_combine( const GLcontext *ctx, GLuint unit, GLuint n,
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GL_BUMP_ENVMAP_ATI:
|
||||
{
|
||||
/* this produces a fixed rgba color, and the coord calc is done elsewhere */
|
||||
for (i = 0; i < n; i++) {
|
||||
/* rgba result is 0,0,0,1 */
|
||||
#if CHAN_TYPE == GL_FLOAT
|
||||
rgba[i][RCOMP] = 0.0;
|
||||
rgba[i][GCOMP] = 0.0;
|
||||
rgba[i][BCOMP] = 0.0;
|
||||
rgba[i][ACOMP] = 1.0;
|
||||
#else
|
||||
rgba[i][RCOMP] = 0;
|
||||
rgba[i][GCOMP] = 0;
|
||||
rgba[i][BCOMP] = 0;
|
||||
rgba[i][ACOMP] = CHAN_MAX;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
return; /* no alpha processing */
|
||||
default:
|
||||
_mesa_problem(ctx, "invalid combine mode");
|
||||
}
|
||||
@@ -1218,12 +1237,86 @@ _swrast_texture_span( GLcontext *ctx, SWspan *span )
|
||||
if (swrast->_AnyTextureCombine)
|
||||
MEMCPY(primary_rgba, span->array->rgba, 4 * span->end * sizeof(GLchan));
|
||||
|
||||
/* First must sample all bump maps */
|
||||
for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
|
||||
if (ctx->Texture.Unit[unit]._ReallyEnabled &&
|
||||
ctx->Texture.Unit[unit]._CurrentCombine->ModeRGB == GL_BUMP_ENVMAP_ATI) {
|
||||
const GLfloat (*texcoords)[4]
|
||||
= (const GLfloat (*)[4])
|
||||
span->array->attribs[FRAG_ATTRIB_TEX0 + unit];
|
||||
GLfloat (*targetcoords)[4]
|
||||
= (GLfloat (*)[4])
|
||||
span->array->attribs[FRAG_ATTRIB_TEX0 +
|
||||
ctx->Texture.Unit[unit].BumpTarget - GL_TEXTURE0];
|
||||
|
||||
const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
|
||||
const struct gl_texture_object *curObj = texUnit->_Current;
|
||||
GLfloat *lambda = span->array->lambda[unit];
|
||||
GLchan (*texels)[4] = (GLchan (*)[4])
|
||||
(swrast->TexelBuffer + unit * (span->end * 4 * sizeof(GLchan)));
|
||||
GLuint i;
|
||||
GLfloat rotMatrix00 = ctx->Texture.Unit[unit].RotMatrix[0];
|
||||
GLfloat rotMatrix01 = ctx->Texture.Unit[unit].RotMatrix[1];
|
||||
GLfloat rotMatrix10 = ctx->Texture.Unit[unit].RotMatrix[2];
|
||||
GLfloat rotMatrix11 = ctx->Texture.Unit[unit].RotMatrix[3];
|
||||
|
||||
/* adjust texture lod (lambda) */
|
||||
if (span->arrayMask & SPAN_LAMBDA) {
|
||||
if (texUnit->LodBias + curObj->LodBias != 0.0F) {
|
||||
/* apply LOD bias, but don't clamp yet */
|
||||
const GLfloat bias = CLAMP(texUnit->LodBias + curObj->LodBias,
|
||||
-ctx->Const.MaxTextureLodBias,
|
||||
ctx->Const.MaxTextureLodBias);
|
||||
GLuint i;
|
||||
for (i = 0; i < span->end; i++) {
|
||||
lambda[i] += bias;
|
||||
}
|
||||
}
|
||||
|
||||
if (curObj->MinLod != -1000.0 || curObj->MaxLod != 1000.0) {
|
||||
/* apply LOD clamping to lambda */
|
||||
const GLfloat min = curObj->MinLod;
|
||||
const GLfloat max = curObj->MaxLod;
|
||||
GLuint i;
|
||||
for (i = 0; i < span->end; i++) {
|
||||
GLfloat l = lambda[i];
|
||||
lambda[i] = CLAMP(l, min, max);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Sample the texture (span->end = number of fragments) */
|
||||
swrast->TextureSample[unit]( ctx, texUnit->_Current, span->end,
|
||||
texcoords, lambda, texels );
|
||||
|
||||
/* manipulate the span values of the bump target
|
||||
not sure this can work correctly even ignoring
|
||||
the problem that channel is unsigned */
|
||||
for (i = 0; i < span->end; i++) {
|
||||
#if CHAN_TYPE == GL_FLOAT
|
||||
targetcoords[i][0] += (texels[i][0] * rotMatrix00 + texels[i][1] *
|
||||
rotMatrix01) / targetcoords[i][3];
|
||||
targetcoords[i][1] += (texels[i][0] * rotMatrix10 + texels[i][1] *
|
||||
rotMatrix11) / targetcoords[i][3];
|
||||
#else
|
||||
targetcoords[i][0] += (CHAN_TO_FLOAT(texels[i][1]) * rotMatrix00 +
|
||||
CHAN_TO_FLOAT(texels[i][1]) * rotMatrix01) /
|
||||
targetcoords[i][3];
|
||||
targetcoords[i][1] += (CHAN_TO_FLOAT(texels[i][0]) * rotMatrix10 +
|
||||
CHAN_TO_FLOAT(texels[i][1]) * rotMatrix11) /
|
||||
targetcoords[i][3];
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Must do all texture sampling before combining in order to
|
||||
* accomodate GL_ARB_texture_env_crossbar.
|
||||
*/
|
||||
for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
|
||||
if (ctx->Texture.Unit[unit]._ReallyEnabled) {
|
||||
if (ctx->Texture.Unit[unit]._ReallyEnabled &&
|
||||
ctx->Texture.Unit[unit]._CurrentCombine->ModeRGB != GL_BUMP_ENVMAP_ATI) {
|
||||
const GLfloat (*texcoords)[4]
|
||||
= (const GLfloat (*)[4])
|
||||
span->array->attribs[FRAG_ATTRIB_TEX0 + unit];
|
||||
|
Reference in New Issue
Block a user