Skip to content

Commit c321fb2

Browse files
committed
fix(ltk_texture): use image_dds for BC1/BC3 TEX decode, fix Dds::height()
- Replace texture2ddecoder BC1/BC3 decode with image_dds (already a dep) to fix corrupted/black pixels caused by wrong pixel format assumptions - Add Rgba8Owned variant to TexSurfaceData for direct RGBA passthrough - Add ImageDds(#[from] image_dds::error::SurfaceError) to DecodeErr - Fix Dds::height() returning width instead of height
1 parent f496cf0 commit c321fb2

File tree

4 files changed

+30
-9
lines changed

4 files changed

+30
-9
lines changed

crates/ltk_texture/src/dds.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ impl Dds {
2525
#[inline]
2626
#[must_use]
2727
pub fn height(&self) -> u32 {
28-
self.file.get_width()
28+
self.file.get_height()
2929
}
3030

3131
/// Get the number of mipmaps in the texture

crates/ltk_texture/src/tex/error.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,6 @@ pub enum DecodeErr {
3131
Bc3(&'static str),
3232
#[error("Could not decode BC1: {0}")]
3333
Bc1(&'static str),
34+
#[error("Could not decode: {0}")]
35+
ImageDds(#[from] image_dds::error::SurfaceError),
3436
}

crates/ltk_texture/src/tex/mod.rs

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -133,26 +133,43 @@ impl Tex {
133133
// size of mip
134134
let (w, h) = mip_dims(level);
135135

136-
let data = match matches!(self.format, Format::Bgra8) {
137-
true => TexSurfaceData::Bgra8Slice(
136+
let data = match self.format {
137+
Format::Bgra8 => TexSurfaceData::Bgra8Slice(
138138
// TODO: test me (this is likely wrong)
139139
&self.data[off..off + (w * h * self.format.bytes_per_block())],
140140
),
141-
false => {
142-
let mut data = vec![0; w * h];
141+
Format::Bc1 | Format::Bc3 => {
142+
let image_format = match self.format {
143+
Format::Bc1 => image_dds::ImageFormat::BC1RgbaUnorm,
144+
Format::Bc3 => image_dds::ImageFormat::BC3RgbaUnorm,
145+
// Safety: outer match guarantees only Bc1/Bc3 reach here
146+
_ => unsafe { unreachable_unchecked() },
147+
};
148+
let surface = image_dds::Surface {
149+
width: w as u32,
150+
height: h as u32,
151+
depth: 1,
152+
layers: 1,
153+
mipmaps: 1,
154+
image_format,
155+
data: &self.data[off..off + mip_bytes((w, h))],
156+
};
157+
let rgba8 = surface.decode_layers_mipmaps_rgba8(0..1, 0..1)?;
158+
TexSurfaceData::Rgba8Owned(rgba8.data)
159+
}
160+
_ => {
161+
let mut data = vec![0u32; w * h];
143162
let i = &self.data[off..off + mip_bytes((w, h))];
144163
let o = &mut data;
145164
match self.format {
146165
Format::Etc1 => {
147166
texture2ddecoder::decode_etc1(i, w, h, o).map_err(DecodeErr::Etc1)
148167
}
149-
Format::Bc1 => texture2ddecoder::decode_bc1(i, w, h, o).map_err(DecodeErr::Bc1),
150-
Format::Bc3 => texture2ddecoder::decode_bc3(i, w, h, o).map_err(DecodeErr::Bc3),
151168
Format::Etc2Eac => {
152169
texture2ddecoder::decode_etc2_rgba8(i, w, h, o).map_err(DecodeErr::Etc2Eac)
153170
}
154-
// Safety: the outer match ensures we can't reach this arm
155-
Format::Bgra8 => unsafe { unreachable_unchecked() },
171+
// Safety: Bgra8/Bc1/Bc3 are handled above
172+
Format::Bgra8 | Format::Bc1 | Format::Bc3 => unsafe { unreachable_unchecked() },
156173
}?;
157174
TexSurfaceData::Bgra8Owned(data)
158175
}

crates/ltk_texture/src/tex/surface.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ pub struct TexSurface<'a> {
1111
pub enum TexSurfaceData<'a> {
1212
Bgra8Slice(&'a [u8]),
1313
Bgra8Owned(Vec<u32>),
14+
Rgba8Owned(Vec<u8>),
1415
}
1516

1617
impl TexSurface<'_> {
@@ -37,6 +38,7 @@ impl TexSurface<'_> {
3738
[r, g, b, a]
3839
})
3940
.collect(),
41+
TexSurfaceData::Rgba8Owned(data) => data,
4042
},
4143
)
4244
.ok_or(ToImageError::InvalidContainerSize)

0 commit comments

Comments
 (0)