glCompressedTextureSubImage2D
Uploads already-compressed blocks (BC7, BC1, ASTC…) into one mip level of a texture.
Part of the family glTexSubImage*
Signature
void glCompressedTextureSubImage2D(GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data);
How it works
Block-compressed formats store each 4×4 pixel block in a fixed number of bytes (8 for BC1, 16 for BC7), and the GPU decodes them while sampling. The data comes ready from a tool or a .dds / .ktx2 file; OpenGL only copies it.
Allocate the texture first with glTextureStorage2D and the same compressed format, then upload every mip level with one call each. imageSize is the byte count of that level: ceil(w/4) × ceil(h/4) × bytes per block.
Parameters
Texture allocated with a compressed internal format.
Mip level.
Left edge, a multiple of 4.
Bottom edge, a multiple of 4.
Width of the region (the level's width for a full upload).
Height of the region.
The compressed format, the same as the storage.
Common values
- GL_COMPRESSED_RGBA_BPTC_UNORM / GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM
- BC7: high quality colour, 16 bytes per block.
- GL_COMPRESSED_RGB_S3TC_DXT1_EXT
- BC1: 8 bytes per block, no real alpha.
- GL_COMPRESSED_RG_RGTC2
- BC5: two channels, for normal maps.
Number of bytes in data.
The compressed blocks.
Tips & pitfalls
Direct State Access (GL 4.5): the object is passed as a parameter, so nothing needs to be bound and no global state is disturbed.
A wrong imageSize gives GL_INVALID_VALUE and nothing is uploaded: the texture stays black.
Errors
When the call is invalid it does nothing and sets an error, which glGetError returns:
- GL_INVALID_VALUE
- imageSize does not match the size of the region in that format.
- GL_INVALID_OPERATION
- format differs from the texture's format, or the offsets are not block aligned.
Example
1glTextureStorage2D(tex, levels, GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM, w, h);
2for (int level = 0; level < levels; ++level) {
3 int lw = std::max(1, w >> level), lh = std::max(1, h >> level);
4 GLsizei bytes = ((lw + 3) / 4) * ((lh + 3) / 4) * 16; // BC7
5 glCompressedTextureSubImage2D(tex, level, 0, 0, lw, lh,
6 GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM, bytes, blocks[level]);
7}