2008/9/5 Christof Sigel christof.sigel@intenode.on.net:
/* since DXT compressed formats are specified in 4x4 pixel blocks devide pitch by 4 */
int srcPitch=srcLockedRect.Pitch>>2;
int destPitch=destLockedRect.Pitch>>2;
That will break with DXT1 surfaces. All the DXT formats are specified in 4x4 blocks, but for DXT1 a 4x4 block is 8 bytes, while for the other DXT formats a block is 16 bytes. This also has implications for how you should handle copying row by row, since each row is 4 pixels high. Strictly speaking you should also verify that the pitch exactly corresponds to the surface width before using the "single memcpy" path, since theory the surface layout in memory could look like this:
|<----width--->| |<-----------pitch------------>| xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx |--------------|xxxxxxxxxxxxxxxx | |xxxxxxxxxxxxxxxx | |xxxxxxxxxxxxxxxx | surface |xxxxxxxxxxxxxxxx | |xxxxxxxxxxxxxxxx | |xxxxxxxxxxxxxxxx | |xxxxxxxxxxxxxxxx |--------------|xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
In other words, for a DXT1 surface with height h, width w and pitch p, you should copy h/4 rows of w*2 bytes, where each row starts at pBits+p*row. For DXT2/3/4/5 you'd copy w*4 bytes for each row. A test for this code would be appreciated.
Thanks for the input, I really should have realised my approach was incorrect as soon as I saw that DXT textures are in blocks. I'm not quite sure how to go about writing a test case, would I just have to create and update surface(s) and check that the resulting surface(s) have been updated correctly?
also, there is another patch coming that can be ignored (I missed some variable name changes that caused my patch to fail to compile), not sure why my mails are showing up late on the mailing list (I am subscribed).
Henri Verbeet wrote:
2008/9/5 Christof Sigel christof.sigel@intenode.on.net:
/* since DXT compressed formats are specified in 4x4 pixel blocks devide pitch by 4 */
int srcPitch=srcLockedRect.Pitch>>2;
int destPitch=destLockedRect.Pitch>>2;
That will break with DXT1 surfaces. All the DXT formats are specified in 4x4 blocks, but for DXT1 a 4x4 block is 8 bytes, while for the other DXT formats a block is 16 bytes. This also has implications for how you should handle copying row by row, since each row is 4 pixels high. Strictly speaking you should also verify that the pitch exactly corresponds to the surface width before using the "single memcpy" path, since theory the surface layout in memory could look like this:
|<----width--->| |<-----------pitch------------>| xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx |--------------|xxxxxxxxxxxxxxxx | |xxxxxxxxxxxxxxxx | |xxxxxxxxxxxxxxxx | surface |xxxxxxxxxxxxxxxx | |xxxxxxxxxxxxxxxx | |xxxxxxxxxxxxxxxx | |xxxxxxxxxxxxxxxx |--------------|xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
In other words, for a DXT1 surface with height h, width w and pitch p, you should copy h/4 rows of w*2 bytes, where each row starts at pBits+p*row. For DXT2/3/4/5 you'd copy w*4 bytes for each row. A test for this code would be appreciated.
2008/9/6 Christof Sigel christof.sigel@intenode.on.net:
Thanks for the input, I really should have realised my approach was incorrect as soon as I saw that DXT textures are in blocks. I'm not quite sure how to go about writing a test case, would I just have to create and update surface(s) and check that the resulting surface(s) have been updated correctly?
Pretty much.