directxdirectdraw

DirectDrawSurface (DDS) pitch computation


I've been studying the DDS format and writing a DDS texture loader for the past two days, just because of curiosity and I ran into something that I used for granted, the "pitch computation formulae". I am really curious as to why they are specified exactly like they are, without any justification.

For example, for block-compressed formats (DXT#n, BC#n), all based on S3TC, the way it is computed is

max( 1, (width+3) / 4 ) * blockSize

So, max gives the bigger of the two values, but why does it work? Why add 3 to the width of the texture and then divide it onto a "nibble-boundary"?

Some legacy types on the other hand are:

(( width+1 ) >> 1) * 4

So, a right shift is basically moving the radix point in a binary basis, or dividing by two. So, why add 1, then divide by two and multiply by 4? To lose the rightmost two bits?

And the last one, for other formats:

( width * bpp + 7) / 8

I understand the bits per pixel and the closest byte boundary division, but why add 7?

Can someone write a bit more about this? Or point me in the right direction?


Solution

  • These calculations are rounding up, as some formats cannot store arbitrary width data. It's important to round up, otherwise you'd lose pixels off the texture. You'll note that usually the add is 1 less than the number being divided by. Integer divides normally round down, so by adding 1 less than the divisor, any number other than an exact multiple will round to the next value.

    For example, if you add 3 then divide by 4:

    The rest of the calculations account for the storage requirements of the respective format. For DXT compression, there are 4x4 blocks of pixels, which is why the size is in 4 pixel chunks, and then each block takes a fixed number of bytes, which is blockSize multiplier.

    The second calculation is rounding to a multiple of 2 pixels, and then multiplying by 4. That suggests perhaps a 16-bit pixel format where pixels are 2 bytes wide and the line must be a multiple of 4 bytes (thus a multiple of two pixels)