Name

    NV_texture_compression_latc

Name Strings

    GL_NV_texture_compression_latc

Contributors

    Contributors to the OpenGL EXT_texture_compression_latc extension
    Greg Roth, NVIDIA

Contact

    Ian Stewart, NVIDIA Corporation (istewart 'at' nvidia.com)

Status

    Complete.

Version

    Last Modifed Date: Oct 26, 2012
    NVIDIA Revision: 1

Number

    OpenGL ES Extension #130

Dependencies

    This extension is written against the OpenGL ES 2.0.25
    Specification.

    This extension interacts with NV_texture_array

Overview

    This extension introduces four new block-based texture compression
    formats suited for unsigned and signed luminance and luminance-alpha
    textures (hence the name "latc" for Luminance-Alpha Texture
    Compression).

    These formats are designed to reduce the storage requirements and
    memory bandwidth required for luminance and luminance-alpha textures
    by a factor of 2-to-1 over conventional uncompressed luminance and
    luminance-alpha textures with 8-bit components.

    The compressed signed luminance-alpha format is reasonably suited
    for storing compressed normal maps.

New Tokens

    Accepted by the <internalformat> parameter of CompressedTexImage2D
    and CompressedTexSubImage2D:

        COMPRESSED_LUMINANCE_LATC1_NV                   0x8C70
        COMPRESSED_SIGNED_LUMINANCE_LATC1_NV            0x8C71
        COMPRESSED_LUMINANCE_ALPHA_LATC2_NV             0x8C72
        COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2_NV      0x8C73

Additions to Chapter 3 of the OpenGL ES 2.0.25 Specification

    Modify Section 3.7.3, "Compressed Texture Images"

    (Replace first two sentences with)

    Texture images may also be specified or modified using image data
    already stored in a known compressed image format.  The GL defines
    some specific compressed formats, and others may be defined by GL
    extensions.

    (Insert after section describing CompressedTexImage2D)

    The specific compressed texture formats supported by
    CompressedTexImage2D, and the corresponding base internal format
    for each specific format, are defined in table 3.X.

        Table 3.X: "Specific compressed texture formats"

        Compressed Internal Formats                Base Internal Format
        ===========================                ====================
        COMPRESSED_LUMINANCE_LATC1_NV              LUMINANCE
        COMPRESSED_SIGNED_LUMINANCE_LATC1_NV       LUMINANCE
        COMPRESSED_LUMINANCE_ALPHA_LATC2_NV        LUMINANCE_ALPHA
        COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2_NV LUMINANCE_ALPHA

    (Replace last paragraph with)

    If the internal format is one of COMPRESSED_LUMINANCE_LATC1_NV,
    COMPRESSED_SIGNED_LUMINANCE_LATC1_NV,
    COMPRESSED_LUMINANCE_ALPHA_LATC2_NV, or
    COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2_NV, the compressed texture
    is stored using one of the two LATC compressed texture image
    encodings and is easily edited along 4x4 texel boundaries. In this
    case, CompressedTexImage2D will result in an INVALID_OPERATION
    error if one of the following conditions occurs:

        * <width> is not a multiple of four, and <width> plus
          <xoffset> is not equal to TEXTURE_WIDTH;

        * <height> is not a multiple of four, and <height> plus
          <yoffset> is not equal to TEXTURE_HEIGHT; or

        * <xoffset> or <yoffset> is not a multiple of four.

    For any other formats, calling CompressedTexSubImage2D will result
    in an INVALID_OPERATION error if <xoffset> or <yoffset> is not
    equal to zero, or if <width> and <height> do not match the width
    and height of the texture, respectively. The contents of any texel
    outside the region modified by the call are undefined. These
    restrictions may be relaxed for other specific compressed internal
    formats whose images are easily modified.

Interactions with NV_texture_array

    If NV_texture_array is supported, the LATC compressed formats may
    also be used as the internal formats given to
    CompressedTexImage3DNV and CompressedTexSubImage3DNV. The
    restrictions for the <width>, <height>, <xoffset>, and <yoffset>
    parameters of the CompressedTexSubImage2D function when used with
    LATC compressed texture formats, described in this extension, also
    apply to the identically named parameters of
    CompressedTexSubImage3DNV.

Errors

    INVALID_OPERATION is generated by CopyTexSubImage2D if the texture
    image <level> bound to <target> has internal format
    COMPRESSED_LUMINANCE_LATC1_NV,
    COMPRESSED_SIGNED_LUMINANCE_LATC1_NV,
    COMPRESSED_LUMINANCE_ALPHA_LATC2_NV, or
    COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2_NV.

    INVALID_OPERATION is generated by CompressedTexSubImage2D if
    <internalformat> is COMPRESSED_LUMINANCE_LATC1_NV,
    COMPRESSED_SIGNED_LUMINANCE_LATC1_NV,
    COMPRESSED_LUMINANCE_ALPHA_LATC2_NV, or
    COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2_NV and any of the
    following apply:

        * <width> is not a multiple of four, and <width> plus
          <xoffset> is not equal to the texture width;

        * <height> is not a multiple of four, and <height> plus
          <yoffset> is not equal to the texture height; or

        * <xoffset> or <yoffset> is not a multiple of four.

New State

    The queries for NUM_COMPRESSED_TEXTURE_FORMATS and
    COMPRESSED_TEXTURE_FORMATS include COMPRESSED_LUMINANCE_LATC1_NV,
    COMPRESSED_SIGNED_LUMINANCE_LATC1_NV,
    COMPRESSED_LUMINANCE_ALPHA_LATC2_NV, and
    COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2_NV.

Appendix

    LATC Compressed Texture Image Formats

    Compressed texture images stored using the LATC compressed image
    encodings are represented as a collection of 4x4 texel blocks,
    where each block contains 64 or 128 bits of texel data.  The image
    is encoded as a normal 2D raster image in which each 4x4 block is
    treated as a single pixel.  If an LATC image has a width or height
    that is not a multiple of four, the data corresponding to texels
    outside the image are irrelevant and undefined.

    When an LATC image with a width of <w>, height of <h>, and block
    size of <blocksize> (8 or 16 bytes) is decoded, the corresponding
    image size (in bytes) is:

        ceil(<w>/4) * ceil(<h>/4) * blocksize.

    When decoding an LATC image, the block containing the texel at
    offset (<x>, <y>) begins at an offset (in bytes) relative to the
    base of the image of:

        blocksize * (ceil(<w>/4) * floor(<y>/4) + floor(<x>/4)).

    The data corresponding to a specific texel (<x>, <y>) are
    extracted from a 4x4 texel block using a relative (x,y) value of

        (<x> modulo 4, <y> modulo 4).

    There are four distinct LATC image formats:

    COMPRESSED_LUMINANCE_LATC1_NV:  Each 4x4 block of texels consists
    of 64 bits of unsigned luminance image data.

        Each luminance image data block is encoded as a sequence of 8
        bytes, called (in order of increasing address):

            lum0, lum1, bits_0, bits_1, bits_2, bits_3, bits_4, bits_5

        The 6 "bits_*" bytes of the block are decoded into a 48-bit
        bit vector:

            bits   = bits_0 +
                     256 * (bits_1 +
                            256 * (bits_2 +
                                   256 * (bits_3 +
                                          256 * (bits_4 +
                                                 256 * bits_5))))

        lum0 and lum1 are 8-bit unsigned integers that are unpacked to
        luminance values LUM0 and LUM1 as though they were pixels with
        a <format> of LUMINANCE and a type of UNSIGNED_BTYE.

        bits is a 48-bit unsigned integer, from which a three-bit control
        code is extracted for a texel at location (x,y) in the block
        using:

            code(x,y) = bits[3*(4*y+x)+2..3*(4*y+x)+0]

        where bit 47 is the most significant and bit 0 is the least
        significant bit.

        The luminance value L for a texel at location (x,y) in the block
        is given by:

            LUM0,              if lum0 > lum1 and code(x,y) == 0
            LUM1,              if lum0 > lum1 and code(x,y) == 1
            (6*LUM0+  LUM1)/7, if lum0 > lum1 and code(x,y) == 2
            (5*LUM0+2*LUM1)/7, if lum0 > lum1 and code(x,y) == 3
            (4*LUM0+3*LUM1)/7, if lum0 > lum1 and code(x,y) == 4
            (3*LUM0+4*LUM1)/7, if lum0 > lum1 and code(x,y) == 5
            (2*LUM0+5*LUM1)/7, if lum0 > lum1 and code(x,y) == 6
            (  LUM0+6*LUM1)/7, if lum0 > lum1 and code(x,y) == 7

            LUM0,              if lum0 <= lum1 and code(x,y) == 0
            LUM1,              if lum0 <= lum1 and code(x,y) == 1
            (4*LUM0+  LUM1)/5, if lum0 <= lum1 and code(x,y) == 2
            (3*LUM0+2*LUM1)/5, if lum0 <= lum1 and code(x,y) == 3
            (2*LUM0+3*LUM1)/5, if lum0 <= lum1 and code(x,y) == 4
            (  LUM0+4*LUM1)/5, if lum0 <= lum1 and code(x,y) == 5
            MINLUM,            if lum0 <= lum1 and code(x,y) == 6
            MAXLUM,            if lum0 <= lum1 and code(x,y) == 7

        MINLUM and MAXLUM are 0.0 and 1.0 respectively.

        Since the decoded texel has a luminance format, the resulting
        RGBA value for the texel is (L,L,L,1).


    COMPRESSED_SIGNED_LUMINANCE_LATC1_NV:  Each 4x4 block of texels
    consists of 64 bits of signed luminance image data.  The luminance
    values of a texel are extracted in the same way as
    COMPRESSED_LUMINANCE_LATC1_NV except lum0, lum1, LUM0, LUM1,
    MINLUM, and MAXLUM are signed values defined as follows:

        lum0 and lum1 are 8-bit signed (two's complement) integers.

               { lum0 / 127.0, lum0 > -128
        LUM0 = {
               { -1.0,         lum0 == -128

               { lum1 / 127.0, lum1 > -128
        LUM1 = {
               { -1.0,         lum1 == -128

        MINLUM = -1.0

        MAXLUM =  1.0

        CAVEAT for signed lum0 and lum1 values: the expressions "lum0
        > lum1" and "lum0 <= lum1" above are considered undefined
        (read: may vary by implementation) when lum0 equals -127 and
        lum1 equals -128, This is because if lum0 were remapped to
        -127 prior to the comparison to reduce the latency of a
        hardware decompressor, the expressions would reverse their
        logic.  Encoders for the signed LA formats should avoid
        encoding blocks where lum0 equals -127 and lum1 equals -128.


    COMPRESSED_LUMINANCE_ALPHA_LATC2_NV:  Each 4x4 block of texels
    consists of 64 bits of compressed unsigned luminance image data
    followed by 64 bits of compressed unsigned alpha image data.

        The first 64 bits of compressed luminance are decoded exactly
        like COMPRESSED_LUMINANCE_LATC1_NV above.

        The second 64 bits of compressed alpha are decoded exactly
        like COMPRESSED_LUMINANCE_LATC1_NV above except the decoded
        value L for this second block is considered the resulting
        alpha value A.

        Since the decoded texel has a luminance-alpha format, the
        resulting RGBA value for the texel is (L,L,L,A).


    COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2_NV:  Each 4x4 block of
    texels consists of 64 bits of compressed signed luminance image
    data followed by 64 bits of compressed signed alpha image data.

        The first 64 bits of compressed luminance are decoded exactly
        like COMPRESSED_SIGNED_LUMINANCE_LATC1_NV above.

        The second 64 bits of compressed alpha are decoded exactly
        like COMPRESSED_SIGNED_LUMINANCE_LATC1_NV above except the
        decoded value L for this second block is considered the
        resulting alpha value A.

        Since this image has a luminance-alpha format, the resulting
        RGBA value is (L,L,L,A).

Issues

    1)  How are signed integer values mapped to floating-point values?

        RESOLVED:  A signed 8-bit two's complement value X is computed
        to a floating-point value Xf with the formula:

                 { X / 127.0, X > -128
            Xf = {
                 { -1.0,      X == -128

        This conversion means -1, 0, and +1 are all exactly
        representable, however -128 and -127 both map to -1.0.
        Mapping -128 to -1.0 avoids the numerical awkwardness of
        having a representable value slightly more negative than -1.0.

    2)  Should the NUM_COMPRESSED_TEXTURE_FORMATS and
        COMPRESSED_TEXTURE_FORMATS queries return the LATC formats?

        RESOLVED:  No.

        The OpenGL ES 2.0.25 specification says "The only values
        returned by this query [GL_COMPRESSED_TEXTURE_FORMATS] are
        those corresponding to 'internalformat' parameters accepted by
        CompressedTexImage2D and suitable for general-purpose usage.
        The renderer will not enumerate formats with restrictions that
        need to be specifically understood prior to use."

        Historically, OpenGL implementations have advertised the RGB
        and RGBA versions of the S3TC extensions compressed format
        tokens through this mechanism.

        The specification is not sufficiently clear about what
        "suitable for general-purpose usage" means.  Historically that
        seems to mean unsigned RGB or unsigned RGBA.  The DXT1 format
        supporting alpha (GL_COMPRESSED_RGBA_S3TC_DXT1_NV) is not
        exposed in the list (at least for NVIDIA drivers) because the
        alpha is always 1.0 except when it is 0.0 when RGB is required
        to be black.  NVIDIA's implementation even limits itself to
        true linear RGB or RGBA formats, specifically not including
        NV_sRGB_formats's sRGB S3TC compressed formats.

        Adding luminance and luminance-alpha texture formats (and
        certainly signed versions of luminance and luminance-alpha
        formats) invites potential comptaibility problems with old
        applications using this mechanism since old applications are
        unlikely to expect non-RGB or non-RGBA formats to be
        advertised through this mechanism.  However no specific
        misinteractions with old applications is known.

        Applications that seek to use the LATC formats should do so by
        looking for this extension's name in the string returned by
        glGetString(GL_EXTENSIONS) rather than what
        GL_NUM_COMPRESSED_TEXTURE_FORMATS and
        GL_COMPRESSED_TEXTURE_FORMATS return.

    3) The EXT_texture_compression_latc extension already lists
       GL_NV_texture_compression_latc as a name string. Do these
       extensions conflict?

       RESOLVED: No.

       The EXT_texture_compression_latc extension, written
       against the OpenGL 1.3 specification, was originally an
       NVIDIA-proprietary extension and published as
       NV_texture_compression_latc. It was later promoted to be an EXT
       extension, in part with S3, and was renamed. However, NVIDIA
       OpenGL implementations continue to expose the
       GL_NV_texture_compression_latc string for legacy reasons.

       This extension, written against the OpenGL ES 2.0.25
       specification, provides a subset of the functionality of
       EXT_texture_compression_latc limited only by the differences
       between the OpenGL 1.3 and OpenGL ES 2.0 specifications. For
       example, format conversion from uncompressed data to compressed
       LATC formats via TexImage2D is not supported by this extension.

       If the driver exporting the GL_NV_texture_compression_latc
       string is an OpenGL ES 2.0 driver (or an OpenGL driver using an
       ES 2.0 profile), this extension describes the available
       functionality. Otherwise, see EXT_texture_compression_latc.

Revision History

    Rev.    Date        Author       Changes
    ----   --------     ---------    -------------------------------------
     1     10/26/2012   istewart     First revision, based of the
                                     EXT_texture_compression_latc
                                     specification.

# vim:ai:ts=4:sts=4:expandtab:textwidth=70
