mesa: add EXT_texture_compression_latc

The encoding/decoding algorithms are shared with RGTC.
Thanks to some magic with the base format, the RGTC texstore functions work
for LATC too.

swrast passes the related piglit tests besides two things:
- The alpha channel is wrong (it's always 1), however the incorrect alpha
  channel makes some other tests fail too, so I guess it's unrelated to LATC.
- Signed LATC fetches aren't correct yet (signed values are clamped to [0,1]),
  however RGTC has the same problem.

Further testing (with other of my patches) shows that hardware drivers
and softpipe work.

BTW, ETQW uses this extension.
This commit is contained in:
Marek Olšák
2011-03-07 02:03:52 +01:00
parent 12fa91b675
commit 7d16e2c0cd
13 changed files with 234 additions and 7 deletions

View File

@@ -181,6 +181,7 @@ static const struct extension extension_table[] = {
{ "GL_EXT_texture3D", o(EXT_texture3D), GL }, { "GL_EXT_texture3D", o(EXT_texture3D), GL },
{ "GL_EXT_texture_array", o(EXT_texture_array), GL }, { "GL_EXT_texture_array", o(EXT_texture_array), GL },
{ "GL_EXT_texture_compression_dxt1", o(EXT_texture_compression_s3tc), GL | ES1 | ES2 }, { "GL_EXT_texture_compression_dxt1", o(EXT_texture_compression_s3tc), GL | ES1 | ES2 },
{ "GL_EXT_texture_compression_latc", o(EXT_texture_compression_latc), GL },
{ "GL_EXT_texture_compression_rgtc", o(ARB_texture_compression_rgtc), GL }, { "GL_EXT_texture_compression_rgtc", o(ARB_texture_compression_rgtc), GL },
{ "GL_EXT_texture_compression_s3tc", o(EXT_texture_compression_s3tc), GL }, { "GL_EXT_texture_compression_s3tc", o(EXT_texture_compression_s3tc), GL },
{ "GL_EXT_texture_cube_map", o(ARB_texture_cube_map), GL }, { "GL_EXT_texture_cube_map", o(ARB_texture_cube_map), GL },
@@ -483,6 +484,7 @@ _mesa_enable_sw_extensions(struct gl_context *ctx)
ctx->Extensions.EXT_stencil_wrap = GL_TRUE; ctx->Extensions.EXT_stencil_wrap = GL_TRUE;
ctx->Extensions.EXT_stencil_two_side = GL_TRUE; ctx->Extensions.EXT_stencil_two_side = GL_TRUE;
ctx->Extensions.EXT_texture_array = GL_TRUE; ctx->Extensions.EXT_texture_array = GL_TRUE;
ctx->Extensions.EXT_texture_compression_latc = GL_TRUE;
ctx->Extensions.EXT_texture_env_add = GL_TRUE; ctx->Extensions.EXT_texture_env_add = GL_TRUE;
ctx->Extensions.EXT_texture_env_combine = GL_TRUE; ctx->Extensions.EXT_texture_env_combine = GL_TRUE;
ctx->Extensions.EXT_texture_env_dot3 = GL_TRUE; ctx->Extensions.EXT_texture_env_dot3 = GL_TRUE;

View File

@@ -927,6 +927,42 @@ static struct gl_format_info format_info[MESA_FORMAT_COUNT] =
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
4, 4, 16 /* 16 bytes per 4x4 block */ 4, 4, 16 /* 16 bytes per 4x4 block */
}, },
{
MESA_FORMAT_L_LATC1,
"MESA_FORMAT_L_LATC1",
GL_LUMINANCE,
GL_UNSIGNED_NORMALIZED,
0, 0, 0, 0,
4, 0, 0, 0, 0,
4, 4, 8 /* 8 bytes per 4x4 block */
},
{
MESA_FORMAT_SIGNED_L_LATC1,
"MESA_FORMAT_SIGNED_L_LATC1",
GL_LUMINANCE,
GL_SIGNED_NORMALIZED,
0, 0, 0, 0,
4, 0, 0, 0, 0,
4, 4, 8 /* 8 bytes per 4x4 block */
},
{
MESA_FORMAT_LA_LATC2,
"MESA_FORMAT_LA_LATC2",
GL_LUMINANCE_ALPHA,
GL_UNSIGNED_NORMALIZED,
0, 0, 0, 4,
4, 0, 0, 0, 0,
4, 4, 16 /* 16 bytes per 4x4 block */
},
{
MESA_FORMAT_SIGNED_LA_LATC2,
"MESA_FORMAT_SIGNED_LA_LATC2",
GL_LUMINANCE_ALPHA,
GL_SIGNED_NORMALIZED,
0, 0, 0, 4,
4, 0, 0, 0, 0,
4, 4, 16 /* 16 bytes per 4x4 block */
},
}; };
@@ -1570,6 +1606,10 @@ _mesa_format_to_type_and_comps(gl_format format,
case MESA_FORMAT_SIGNED_RED_RGTC1: case MESA_FORMAT_SIGNED_RED_RGTC1:
case MESA_FORMAT_RG_RGTC2: case MESA_FORMAT_RG_RGTC2:
case MESA_FORMAT_SIGNED_RG_RGTC2: case MESA_FORMAT_SIGNED_RG_RGTC2:
case MESA_FORMAT_L_LATC1:
case MESA_FORMAT_SIGNED_L_LATC1:
case MESA_FORMAT_LA_LATC2:
case MESA_FORMAT_SIGNED_LA_LATC2:
/* XXX generate error instead? */ /* XXX generate error instead? */
*datatype = GL_UNSIGNED_BYTE; *datatype = GL_UNSIGNED_BYTE;
*comps = 0; *comps = 0;

View File

@@ -185,6 +185,14 @@ typedef enum
MESA_FORMAT_RG_RGTC2, MESA_FORMAT_RG_RGTC2,
MESA_FORMAT_SIGNED_RG_RGTC2, MESA_FORMAT_SIGNED_RG_RGTC2,
/*@}*/ /*@}*/
/*@{*/
MESA_FORMAT_L_LATC1,
MESA_FORMAT_SIGNED_L_LATC1,
MESA_FORMAT_LA_LATC2,
MESA_FORMAT_SIGNED_LA_LATC2,
/*@}*/
MESA_FORMAT_COUNT MESA_FORMAT_COUNT
} gl_format; } gl_format;

View File

@@ -743,6 +743,10 @@ _mesa_is_color_format(GLenum format)
case GL_COMPRESSED_SIGNED_RED_RGTC1: case GL_COMPRESSED_SIGNED_RED_RGTC1:
case GL_COMPRESSED_RG_RGTC2: case GL_COMPRESSED_RG_RGTC2:
case GL_COMPRESSED_SIGNED_RG_RGTC2: case GL_COMPRESSED_SIGNED_RG_RGTC2:
case GL_COMPRESSED_LUMINANCE_LATC1_EXT:
case GL_COMPRESSED_SIGNED_LUMINANCE_LATC1_EXT:
case GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT:
case GL_COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2_EXT:
/* signed, normalized texture formats */ /* signed, normalized texture formats */
case GL_RGBA_SNORM: case GL_RGBA_SNORM:
case GL_RGBA8_SNORM: case GL_RGBA8_SNORM:
@@ -1025,6 +1029,11 @@ _mesa_is_compressed_format(struct gl_context *ctx, GLenum format)
case GL_COMPRESSED_RG_RGTC2: case GL_COMPRESSED_RG_RGTC2:
case GL_COMPRESSED_SIGNED_RG_RGTC2: case GL_COMPRESSED_SIGNED_RG_RGTC2:
return ctx->Extensions.ARB_texture_compression_rgtc; return ctx->Extensions.ARB_texture_compression_rgtc;
case GL_COMPRESSED_LUMINANCE_LATC1_EXT:
case GL_COMPRESSED_SIGNED_LUMINANCE_LATC1_EXT:
case GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT:
case GL_COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2_EXT:
return ctx->Extensions.EXT_texture_compression_latc;
default: default:
return GL_FALSE; return GL_FALSE;
} }

View File

@@ -1764,8 +1764,13 @@ _mesa_generate_mipmap(struct gl_context *ctx, GLenum target,
} else if (srcImage->_BaseFormat == GL_RGBA) { } else if (srcImage->_BaseFormat == GL_RGBA) {
convertFormat = MESA_FORMAT_RGBA8888; convertFormat = MESA_FORMAT_RGBA8888;
components = 4; components = 4;
} } else if (srcImage->_BaseFormat == GL_LUMINANCE) {
else { convertFormat = MESA_FORMAT_L8;
components = 1;
} else if (srcImage->_BaseFormat == GL_LUMINANCE_ALPHA) {
convertFormat = MESA_FORMAT_AL88;
components = 2;
} else {
_mesa_problem(ctx, "bad srcImage->_BaseFormat in _mesa_generate_mipmaps"); _mesa_problem(ctx, "bad srcImage->_BaseFormat in _mesa_generate_mipmaps");
return; return;
} }

View File

@@ -2802,6 +2802,7 @@ struct gl_extensions
GLboolean EXT_texture_object; GLboolean EXT_texture_object;
GLboolean EXT_texture3D; GLboolean EXT_texture3D;
GLboolean EXT_texture_array; GLboolean EXT_texture_array;
GLboolean EXT_texture_compression_latc;
GLboolean EXT_texture_compression_s3tc; GLboolean EXT_texture_compression_s3tc;
GLboolean EXT_texture_env_add; GLboolean EXT_texture_env_add;
GLboolean EXT_texture_env_combine; GLboolean EXT_texture_env_combine;

View File

@@ -173,6 +173,15 @@ _mesa_glenum_to_compressed_format(GLenum format)
case GL_COMPRESSED_SIGNED_RG_RGTC2: case GL_COMPRESSED_SIGNED_RG_RGTC2:
return MESA_FORMAT_SIGNED_RG_RGTC2; return MESA_FORMAT_SIGNED_RG_RGTC2;
case GL_COMPRESSED_LUMINANCE_LATC1_EXT:
return MESA_FORMAT_L_LATC1;
case GL_COMPRESSED_SIGNED_LUMINANCE_LATC1_EXT:
return MESA_FORMAT_SIGNED_L_LATC1;
case GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT:
return MESA_FORMAT_LA_LATC2;
case GL_COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2_EXT:
return MESA_FORMAT_SIGNED_LA_LATC2;
default: default:
return MESA_FORMAT_NONE; return MESA_FORMAT_NONE;
} }
@@ -229,6 +238,15 @@ _mesa_compressed_format_to_glenum(struct gl_context *ctx, GLuint mesaFormat)
case MESA_FORMAT_SIGNED_RG_RGTC2: case MESA_FORMAT_SIGNED_RG_RGTC2:
return GL_COMPRESSED_SIGNED_RG_RGTC2; return GL_COMPRESSED_SIGNED_RG_RGTC2;
case MESA_FORMAT_L_LATC1:
return GL_COMPRESSED_LUMINANCE_LATC1_EXT;
case MESA_FORMAT_SIGNED_L_LATC1:
return GL_COMPRESSED_SIGNED_LUMINANCE_LATC1_EXT;
case MESA_FORMAT_LA_LATC2:
return GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT;
case MESA_FORMAT_SIGNED_LA_LATC2:
return GL_COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2_EXT;
default: default:
_mesa_problem(ctx, "Unexpected mesa texture format in" _mesa_problem(ctx, "Unexpected mesa texture format in"
" _mesa_compressed_format_to_glenum()"); " _mesa_compressed_format_to_glenum()");

View File

@@ -98,7 +98,8 @@ _mesa_texstore_red_rgtc1(TEXSTORE_PARAMS)
GLubyte srcpixels[4][4]; GLubyte srcpixels[4][4];
GLubyte *blkaddr; GLubyte *blkaddr;
GLint dstRowDiff; GLint dstRowDiff;
ASSERT(dstFormat == MESA_FORMAT_RED_RGTC1); ASSERT(dstFormat == MESA_FORMAT_RED_RGTC1 ||
dstFormat == MESA_FORMAT_L_LATC1);
ASSERT(dstXoffset % 4 == 0); ASSERT(dstXoffset % 4 == 0);
ASSERT(dstYoffset % 4 == 0); ASSERT(dstYoffset % 4 == 0);
ASSERT(dstZoffset % 4 == 0); ASSERT(dstZoffset % 4 == 0);
@@ -153,7 +154,8 @@ _mesa_texstore_signed_red_rgtc1(TEXSTORE_PARAMS)
GLbyte srcpixels[4][4]; GLbyte srcpixels[4][4];
GLbyte *blkaddr; GLbyte *blkaddr;
GLint dstRowDiff; GLint dstRowDiff;
ASSERT(dstFormat == MESA_FORMAT_SIGNED_RED_RGTC1); ASSERT(dstFormat == MESA_FORMAT_SIGNED_RED_RGTC1 ||
dstFormat == MESA_FORMAT_SIGNED_L_LATC1);
ASSERT(dstXoffset % 4 == 0); ASSERT(dstXoffset % 4 == 0);
ASSERT(dstYoffset % 4 == 0); ASSERT(dstYoffset % 4 == 0);
ASSERT(dstZoffset % 4 == 0); ASSERT(dstZoffset % 4 == 0);
@@ -208,7 +210,8 @@ _mesa_texstore_rg_rgtc2(TEXSTORE_PARAMS)
GLubyte *blkaddr; GLubyte *blkaddr;
GLint dstRowDiff; GLint dstRowDiff;
ASSERT(dstFormat == MESA_FORMAT_RG_RGTC2); ASSERT(dstFormat == MESA_FORMAT_RG_RGTC2 ||
dstFormat == MESA_FORMAT_LA_LATC2);
ASSERT(dstXoffset % 4 == 0); ASSERT(dstXoffset % 4 == 0);
ASSERT(dstYoffset % 4 == 0); ASSERT(dstYoffset % 4 == 0);
ASSERT(dstZoffset % 4 == 0); ASSERT(dstZoffset % 4 == 0);
@@ -269,7 +272,8 @@ _mesa_texstore_signed_rg_rgtc2(TEXSTORE_PARAMS)
GLbyte *blkaddr; GLbyte *blkaddr;
GLint dstRowDiff; GLint dstRowDiff;
ASSERT(dstFormat == MESA_FORMAT_SIGNED_RG_RGTC2); ASSERT(dstFormat == MESA_FORMAT_SIGNED_RG_RGTC2 ||
dstFormat == MESA_FORMAT_SIGNED_LA_LATC2);
ASSERT(dstXoffset % 4 == 0); ASSERT(dstXoffset % 4 == 0);
ASSERT(dstYoffset % 4 == 0); ASSERT(dstYoffset % 4 == 0);
ASSERT(dstZoffset % 4 == 0); ASSERT(dstZoffset % 4 == 0);
@@ -374,6 +378,62 @@ _mesa_fetch_texel_2d_f_signed_rg_rgtc2(const struct gl_texture_image *texImage,
texel[ACOMP] = 1.0; texel[ACOMP] = 1.0;
} }
void
_mesa_fetch_texel_2d_f_l_latc1(const struct gl_texture_image *texImage,
GLint i, GLint j, GLint k, GLfloat *texel)
{
GLubyte red;
unsigned_fetch_texel_rgtc(texImage->RowStride, (GLubyte *)(texImage->Data),
i, j, &red, 1);
texel[RCOMP] =
texel[GCOMP] =
texel[BCOMP] = UBYTE_TO_FLOAT(red);
texel[ACOMP] = 1.0;
}
void
_mesa_fetch_texel_2d_f_signed_l_latc1(const struct gl_texture_image *texImage,
GLint i, GLint j, GLint k, GLfloat *texel)
{
GLbyte red;
signed_fetch_texel_rgtc(texImage->RowStride, (GLbyte *)(texImage->Data),
i, j, &red, 1);
texel[RCOMP] =
texel[GCOMP] =
texel[BCOMP] = BYTE_TO_FLOAT_TEX(red);
texel[ACOMP] = 1.0;
}
void
_mesa_fetch_texel_2d_f_la_latc2(const struct gl_texture_image *texImage,
GLint i, GLint j, GLint k, GLfloat *texel)
{
GLubyte red, green;
unsigned_fetch_texel_rgtc(texImage->RowStride, (GLubyte *)(texImage->Data),
i, j, &red, 2);
unsigned_fetch_texel_rgtc(texImage->RowStride, (GLubyte *)(texImage->Data) + 8,
i, j, &green, 2);
texel[RCOMP] =
texel[GCOMP] =
texel[BCOMP] = UBYTE_TO_FLOAT(red);
texel[ACOMP] = UBYTE_TO_FLOAT(green);
}
void
_mesa_fetch_texel_2d_f_signed_la_latc2(const struct gl_texture_image *texImage,
GLint i, GLint j, GLint k, GLfloat *texel)
{
GLbyte red, green;
signed_fetch_texel_rgtc(texImage->RowStride, (GLbyte *)(texImage->Data),
i, j, &red, 2);
signed_fetch_texel_rgtc(texImage->RowStride, (GLbyte *)(texImage->Data) + 8,
i, j, &green, 2);
texel[RCOMP] =
texel[GCOMP] =
texel[BCOMP] = BYTE_TO_FLOAT_TEX(red);
texel[ACOMP] = BYTE_TO_FLOAT_TEX(green);
}
#define TAG(x) unsigned_##x #define TAG(x) unsigned_##x
#define TYPE GLubyte #define TYPE GLubyte

View File

@@ -57,4 +57,21 @@ _mesa_fetch_texel_2d_f_rg_rgtc2(const struct gl_texture_image *texImage,
extern void extern void
_mesa_fetch_texel_2d_f_signed_rg_rgtc2(const struct gl_texture_image *texImage, _mesa_fetch_texel_2d_f_signed_rg_rgtc2(const struct gl_texture_image *texImage,
GLint i, GLint j, GLint k, GLfloat *texel); GLint i, GLint j, GLint k, GLfloat *texel);
extern void
_mesa_fetch_texel_2d_f_l_latc1(const struct gl_texture_image *texImage,
GLint i, GLint j, GLint k, GLfloat *texel);
extern void
_mesa_fetch_texel_2d_f_signed_l_latc1(const struct gl_texture_image *texImage,
GLint i, GLint j, GLint k, GLfloat *texel);
extern void
_mesa_fetch_texel_2d_f_la_latc2(const struct gl_texture_image *texImage,
GLint i, GLint j, GLint k, GLfloat *texel);
extern void
_mesa_fetch_texel_2d_f_signed_la_latc2(const struct gl_texture_image *texImage,
GLint i, GLint j, GLint k, GLfloat *texel);
#endif #endif

View File

@@ -786,6 +786,34 @@ texfetch_funcs[MESA_FORMAT_COUNT] =
NULL, NULL,
NULL NULL
}, },
{
MESA_FORMAT_L_LATC1,
NULL,
_mesa_fetch_texel_2d_f_l_latc1,
NULL,
NULL
},
{
MESA_FORMAT_SIGNED_L_LATC1,
NULL,
_mesa_fetch_texel_2d_f_signed_l_latc1,
NULL,
NULL
},
{
MESA_FORMAT_LA_LATC2,
NULL,
_mesa_fetch_texel_2d_f_la_latc2,
NULL,
NULL
},
{
MESA_FORMAT_SIGNED_LA_LATC2,
NULL,
_mesa_fetch_texel_2d_f_signed_la_latc2,
NULL,
NULL
},
}; };

View File

@@ -621,6 +621,25 @@ _mesa_choose_tex_format( struct gl_context *ctx, GLint internalFormat,
} }
} }
if (ctx->Extensions.EXT_texture_compression_latc) {
switch (internalFormat) {
case GL_COMPRESSED_LUMINANCE_LATC1_EXT:
RETURN_IF_SUPPORTED(MESA_FORMAT_L_LATC1);
break;
case GL_COMPRESSED_SIGNED_LUMINANCE_LATC1_EXT:
RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_L_LATC1);
break;
case GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT:
RETURN_IF_SUPPORTED(MESA_FORMAT_LA_LATC2);
break;
case GL_COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2_EXT:
RETURN_IF_SUPPORTED(MESA_FORMAT_SIGNED_LA_LATC2);
break;
default:
; /* fallthrough */
}
}
_mesa_problem(ctx, "unexpected format in _mesa_choose_tex_format()"); _mesa_problem(ctx, "unexpected format in _mesa_choose_tex_format()");
return MESA_FORMAT_NONE; return MESA_FORMAT_NONE;
} }

View File

@@ -509,6 +509,19 @@ _mesa_base_tex_format( struct gl_context *ctx, GLint internalFormat )
} }
} }
if (ctx->Extensions.EXT_texture_compression_latc) {
switch (internalFormat) {
case GL_COMPRESSED_LUMINANCE_LATC1_EXT:
case GL_COMPRESSED_SIGNED_LUMINANCE_LATC1_EXT:
return GL_LUMINANCE;
case GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT:
case GL_COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2_EXT:
return GL_LUMINANCE_ALPHA;
default:
; /* fallthrough */
}
}
return -1; /* error */ return -1; /* error */
} }

View File

@@ -4135,7 +4135,14 @@ texstore_funcs[MESA_FORMAT_COUNT] =
{ MESA_FORMAT_RED_RGTC1, _mesa_texstore_red_rgtc1 }, { MESA_FORMAT_RED_RGTC1, _mesa_texstore_red_rgtc1 },
{ MESA_FORMAT_SIGNED_RED_RGTC1, _mesa_texstore_signed_red_rgtc1 }, { MESA_FORMAT_SIGNED_RED_RGTC1, _mesa_texstore_signed_red_rgtc1 },
{ MESA_FORMAT_RG_RGTC2, _mesa_texstore_rg_rgtc2 }, { MESA_FORMAT_RG_RGTC2, _mesa_texstore_rg_rgtc2 },
{ MESA_FORMAT_SIGNED_RG_RGTC2, _mesa_texstore_signed_rg_rgtc2 } { MESA_FORMAT_SIGNED_RG_RGTC2, _mesa_texstore_signed_rg_rgtc2 },
/* Re-use the R/RG texstore functions.
* The code is generic enough to handle LATC too. */
{ MESA_FORMAT_L_LATC1, _mesa_texstore_red_rgtc1 },
{ MESA_FORMAT_SIGNED_L_LATC1, _mesa_texstore_signed_red_rgtc1 },
{ MESA_FORMAT_LA_LATC2, _mesa_texstore_rg_rgtc2 },
{ MESA_FORMAT_SIGNED_LA_LATC2, _mesa_texstore_signed_rg_rgtc2 }
}; };