Problem with glCompressTexSubImage2D

can’t get the updating of the compressed texture to work right. I’m trying to update a small portion within the compressed texture. Here’s my code:

Initialization

glGenTextures(1, &m_id);
glBindTexture(GL_TEXTURE_2D, m_id);
// other stuff
glTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);

Updating

glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
glPixelStorei(GL_UNPACK_ROW_LENGTH, m_width);
glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
static int internalFormat;
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &internalFormat);
glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, xOffset, yOffset, width, height, internalFormat, widthheightm_bpp, buff);

After I update the texture, nothing shows up. Its still the same texture. And I am updating the data in buff, so its not that. Does anybody know what I"m doing wrong ?

Is xOffset,yOffset and width,height a multiple of 4?

The S3TC texture compression spec requires this.

Spec:

Since the S3TC texture compression algorithm supports only 2D
images, CompressedTexSubImage1DARB and CompressedTexSubImage3DARB produce
an INVALID_ENUM error if <format> is an S3TC format. Since S3TC images
are easily edited along 4x4 texel boundaries, the limitations on
CompressedTexSubImage2D are relaxed. CompressedTexSubImage2D will result
in an INVALID_OPERATION error only if one of the following conditions
occurs:

    * &lt;width&gt; is not a multiple of four or equal to TEXTURE_WIDTH.
    * &lt;height&gt; is not a multiple of four or equal to TEXTURE_HEIGHT.
    * &lt;xoffset&gt; or &lt;yoffset&gt; is not a multiple of four.

The contents of any 4x4 block of texels of an S3TC compressed texture
image that does not intersect the area being modified are preserved during
valid TexSubImage2D and CopyTexSubImage2D calls.

Also the line where you get the internal format of the texture and then use that as the incomming format of the data looks problematic. (you should already know the format of the incomming data - Doing this will cause problems if your incomming data is not in the texture format)

This bring me to an issue I really care about. Can I (currently) depend on DXTn (1-5)? It wold be quite enjoyable to have the DX “luxury” of D3D to save textures in a DXTn format, then load them up on any card that support texture compression, and it does work with this.

I don’t know any hardware supporting compressed texctures that doesn’t support DXTn, but DX users has a promise. As an OpenGL programmer I have, at best, a vague “maybe”.

Huh? Unless you are talking about D3D10, the current D3D9c has a Cap bit that should be checked for DXT texture support in hardware (Adapter formats->Texture formats). (Some of the D3DX methods will do a conversion on load if not supported however)

How is that any different from checking if GL_EXT_texture_compression_s3tc is supported? (Besides, so many games use it, it is a given nowdays - supported since Geforce 1 http://www.delphi3d.net/hardware/extsupport.php?extension=GL_EXT_texture_compression_s3tc))

Originally posted by sqrt[-1]:
[b]Is xOffset,yOffset and width,height a multiple of 4?

The S3TC texture compression spec requires this.

Spec:[/b]
Its still not working. I made sure that the width, height, xoffset and yoffset were ALL a multiple of 4, but still the texture is not updated.

            xOffset = int(xOffset / 4) * 4;
            yOffset = int(yOffset / 4) * 4;
            width = int(width / 4) * 4;
            height = int(height / 4) * 4;
            glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, xOffset, yOffset, width, height, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, width*height*m_bpp, buff);

Arr, of course! I should have seen this sooner!

These commands do not provide for image
format conversion, so an INVALID OPERATION error results if format does
not match the internal format of the texture image being modified. If the image-
Size parameter is not consistent with the format, dimensions, and contents of the
compressed image (too little or too much data), an INVALID VALUE error results.

The image size parameter is most probably wrong! (It is the compressed image size data you are supplying that is checked against what you expect)
What is m_Bpp? This is what it should look like for DXT1:

(widthheight4)/8

DXT3/5:

(width*height)

Just as a side note: You ARE supplying compressed image data right? otherwise you should be using the standard glTexSubImage2D. (It will compress it when it loads it in to DXT texture surfaces - not a very nioce looking compression but it does work)

Originally posted by sqrt[-1]:
[b]

The image size parameter is most probably wrong! (It is the compressed image size data you are supplying that is checked against what you expect)
What is m_Bpp? This is what it should look like for DXT1:

(widthheight4)/8

DXT3/5:

(width*height)

Just as a side note: You ARE supplying compressed image data right? otherwise you should be using the standard glTexSubImage2D. (It will compress it when it loads it in to DXT texture surfaces - not a very nioce looking compression but it does work)[/b]
Actually no I was not supplying compressed data. I was giving it uncompressed data. So how should I go about updating it with glTexSubImage2D? I tried the following 2 things and it did not work.

glTexSubImage2D(GL_TEXTURE_2D, 0, xOffset, yOffset, width, height, GL_RGB, GL_UNSIGNED_BYTE, buff);

and

glTexSubImage2D(GL_TEXTURE_2D, 0, xOffset, yOffset, width, height, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE, buff);

Both of these did not seem to work. Any ideas ?

Your first one:
glTexSubImage2D(GL_TEXTURE_2D, 0, xOffset, yOffset, width, height, GL_RGB, GL_UNSIGNED_BYTE, buff);

should work. (xOffset, yOffset, width/height still a multiple of 4?)

Perhaps this would be easier if you could post a link to an example program that I could take a look at?

Yep, that was the problem. I forgot to reset offsetX, offsetY and width, height to a power of 4. Thanks a lot, it works now.