From: Stefan Dösinger Subject: [PATCH 1/4] wined3d: Properly up-scale WINED3DFMT_R5G5_SNORM_L6_UNORM. Message-Id: <1425331752-18763-1-git-send-email-stefan@codeweavers.com> Date: Mon, 2 Mar 2015 22:29:09 +0100 Simply left-shifting is not enough in positive ranges. 0xff / 255 != 0xff00 / 65535. Using the compiler to read 5 bit signed values seems a lot easier than operating with masks. --- dlls/wined3d/utils.c | 44 +++++++++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c index 1ce23ac..67457d5 100644 --- a/dlls/wined3d/utils.c +++ b/dlls/wined3d/utils.c @@ -290,6 +290,15 @@ static void convert_l4a4_unorm(const BYTE *src, BYTE *dst, UINT src_row_pitch, U } } +#include +struct r5g5l6 +{ + signed r : 5; + signed g : 5; + unsigned l : 6; +}; +#include + static void convert_r5g5_snorm_l6_unorm(const BYTE *src, BYTE *dst, UINT src_row_pitch, UINT src_slice_pitch, UINT dst_row_pitch, UINT dst_slice_pitch, UINT width, UINT height, UINT depth) { @@ -322,8 +331,8 @@ static void convert_r5g5_snorm_l6_unorm_nv(const BYTE *src, BYTE *dst, UINT src_ UINT dst_row_pitch, UINT dst_slice_pitch, UINT width, UINT height, UINT depth) { unsigned int x, y, z; - const WORD *Source; - unsigned char *Dest; + unsigned char *texel_out, out_ds, out_dt; + const struct r5g5l6 *texel_in; /* This makes the gl surface bigger(24 bit instead of 16), but it works with * fixed function and shaders without further conversion once the surface is @@ -333,27 +342,24 @@ static void convert_r5g5_snorm_l6_unorm_nv(const BYTE *src, BYTE *dst, UINT src_ { for (y = 0; y < height; y++) { - Source = (const WORD *)(src + z * src_slice_pitch + y * src_row_pitch); - Dest = dst + z * dst_slice_pitch + y * dst_row_pitch; + texel_in = (const struct r5g5l6 *)(src + z * src_slice_pitch + y * src_row_pitch); + texel_out = dst + z * dst_slice_pitch + y * dst_row_pitch; for (x = 0; x < width; x++ ) { - short color = (*Source++); - unsigned char l = ((color >> 10) & 0xfc); - char v = ((color >> 5) & 0x3e); - char u = ((color ) & 0x1f); + out_ds = texel_in->r << 3; + if (texel_in->r > 0) + out_ds |= texel_in->r >> 1; - /* 8 bits destination, 6 bits source, 8th bit is the sign. gl ignores the sign - * and doubles the positive range. Thus shift left only once, gl does the 2nd - * shift. GL reads a signed value and converts it into an unsigned value. - */ - /* M */ Dest[2] = l << 1; + out_dt = texel_in->g << 3; + if (texel_in->g > 0) + out_dt |= texel_in->g >> 1; - /* Those are read as signed, but kept signed. Just left-shift 3 times to scale - * from 5 bit values to 8 bit values. - */ - /* V */ Dest[1] = v << 3; - /* U */ Dest[0] = u << 3; - Dest += 3; + texel_out[0] = out_ds; + texel_out[1] = out_dt; + texel_out[2] = texel_in->l << 1 | texel_in->l >> 5; + + texel_out += 3; + texel_in++; } } } -- 2.3.0