I’m getting GL_INVALID_OPERATION on glCompressedTexSubImage2D and don’t know why.

The texture has been sucessfully created via glTexImage2D(), using GL_COMPRESSED_RGB_S3TC_DXT1 as internal fomat and a null pointer, which should just reserve the texture memory.

After creation I need to update sub blocks of the texture via glCompressedTexImage2D. The very first upload, put at (0,0), works. The next block is being updated at (136,0).
The upload offsets and sizes are all aligned to 4, meeting the requirements of S3TC.

I went into the specs of EXT_texture_compression_s3tc and found

Add to Section 3.8.2,

CompressedTexSubImage2D will result
in an INVALID_OPERATION error only if one of the following conditions

    * <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

Bummer! This means, for whatver stupid reason, each subimage upload MUST fill the complete upper right ‘quadrant’.
But then, later on the specs say:

The following restrictions from the ARB_texture_compression specification
do not apply to S3TC texture formats, since subimage modification is
straightforward as long as the subimage is properly aligned.

DELETE: INVALID_VALUE is generated by CompressedTexSubImage1DARB,
DELETE: CompressedTexSubImage2DARB, or CompressedTexSubImage3DARB if the
DELETE: entire texture image is not being edited: if <xoffset>,
DELETE: <yoffset>, or <zoffset> is greater than -b, <xoffset> + <width> is
DELETE: less than w+b, <yoffset> + <height> is less than h+b, or <zoffset>
DELETE: + <depth> is less than d+b, where b is the value of
DELETE: TEXTURE_BORDER, w is the value of TEXTURE_WIDTH, h is the value of

This lifts the restriction from above, allowing to freely update any aligned-to-4 blocks of the texture.
So, why am I getting GL_INVALID_OPERATION then?

I’m using a GF8800GTS, 195.39 on WinXP64

Actually, there’s no bug. It seems, I tricked myself via a wrong glActiveTexture() state. The very first upload always worked, then some other code changed glActiveTexture, and then, the next glCompressedTexSubImage referred to the wrong texture, correctly leading to GL_INVALID_OPERATION. Damn selectors!