[PATCH 5/5] d3dx9: Handle pixel formats larger than 32 bits in surface loading / filtering functions.

Matteo Bruni mbruni at codeweavers.com
Fri Feb 14 08:53:13 CST 2014


---
 dlls/d3dx9_36/d3dx9_36_private.h |   1 +
 dlls/d3dx9_36/math.c             |   2 +-
 dlls/d3dx9_36/surface.c          | 196 ++++++++++++++++++++-------------------
 3 files changed, 101 insertions(+), 98 deletions(-)

diff --git a/dlls/d3dx9_36/d3dx9_36_private.h b/dlls/d3dx9_36/d3dx9_36_private.h
index 83d4de9..0aef8cd 100644
--- a/dlls/d3dx9_36/d3dx9_36_private.h
+++ b/dlls/d3dx9_36/d3dx9_36_private.h
@@ -98,6 +98,7 @@ HRESULT load_volume_texture_from_dds(IDirect3DVolumeTexture9 *volume_texture, co
     const PALETTEENTRY *palette, DWORD filter, DWORD color_key, const D3DXIMAGE_INFO *src_info) DECLSPEC_HIDDEN;
 
 unsigned short float_32_to_16(const float in) DECLSPEC_HIDDEN;
+float float_16_to_32(const unsigned short in) DECLSPEC_HIDDEN;
 
 /* debug helpers */
 const char *debug_d3dxparameter_class(D3DXPARAMETER_CLASS c) DECLSPEC_HIDDEN;
diff --git a/dlls/d3dx9_36/math.c b/dlls/d3dx9_36/math.c
index f98927f..09c055e 100644
--- a/dlls/d3dx9_36/math.c
+++ b/dlls/d3dx9_36/math.c
@@ -2226,7 +2226,7 @@ D3DXFLOAT16 *WINAPI D3DXFloat32To16Array(D3DXFLOAT16 *pout, const FLOAT *pin, UI
 
 /* Native d3dx9's D3DXFloat16to32Array lacks support for NaN and Inf. Specifically, e = 16 is treated as a
  * regular number - e.g., 0x7fff is converted to 131008.0 and 0xffff to -131008.0. */
-static inline float float_16_to_32(const unsigned short in)
+float float_16_to_32(const unsigned short in)
 {
     const unsigned short s = (in & 0x8000);
     const unsigned short e = (in & 0x7C00) >> 10;
diff --git a/dlls/d3dx9_36/surface.c b/dlls/d3dx9_36/surface.c
index 48d129e..bcd0f60 100644
--- a/dlls/d3dx9_36/surface.c
+++ b/dlls/d3dx9_36/surface.c
@@ -1339,33 +1339,6 @@ static void init_argb_conversion_info(const struct pixel_format_desc *srcformat,
     }
 }
 
-static DWORD dword_from_bytes(const BYTE *src, UINT bytes_per_pixel)
-{
-    DWORD ret = 0;
-    static BOOL fixme_once;
-
-    if(bytes_per_pixel > sizeof(DWORD)) {
-        if(!fixme_once++) FIXME("Unsupported image: %u bytes per pixel\n", bytes_per_pixel);
-        bytes_per_pixel = sizeof(DWORD);
-    }
-
-    memcpy(&ret, src, bytes_per_pixel);
-    return ret;
-}
-
-static void dword_to_bytes(BYTE *dst, DWORD dword, UINT bytes_per_pixel)
-{
-    static BOOL fixme_once;
-
-    if(bytes_per_pixel > sizeof(DWORD)) {
-        if(!fixme_once++) FIXME("Unsupported image: %u bytes per pixel\n", bytes_per_pixel);
-        ZeroMemory(dst, bytes_per_pixel);
-        bytes_per_pixel = sizeof(DWORD);
-    }
-
-    memcpy(dst, &dword, bytes_per_pixel);
-}
-
 /************************************************************
  * get_relevant_argb_components
  *
@@ -1403,55 +1376,78 @@ static DWORD make_argb_color(const struct argb_conversion_info *info, const DWOR
     return val;
 }
 
-static void format_to_vec4(const struct pixel_format_desc *format, const DWORD *src, struct vec4 *dst)
+/* It doesn't work for components bigger than 32 bits (or somewhat smaller but unaligned). */
+static void format_to_vec4(const struct pixel_format_desc *format, const BYTE *src, struct vec4 *dst)
 {
-    DWORD mask;
+    DWORD mask, tmp;
+    unsigned int c;
 
-    if (format->bits[1])
+    for (c = 0; c < 4; ++c)
     {
-        mask = (1 << format->bits[1]) - 1;
-        dst->x = (float)((*src >> format->shift[1]) & mask) / mask;
-    }
-    else
-        dst->x = 1.0f;
+        static const unsigned int component_offsets[4] = {3, 0, 1, 2};
+        float *dst_component = (float *)dst + component_offsets[c];
 
-    if (format->bits[2])
-    {
-        mask = (1 << format->bits[2]) - 1;
-        dst->y = (float)((*src >> format->shift[2]) & mask) / mask;
-    }
-    else
-        dst->y = 1.0f;
+        if (format->bits[c])
+        {
+            mask = format->bits[c] == 32 ? ~0U : (1 << format->bits[c]) - 1;
 
-    if (format->bits[3])
-    {
-        mask = (1 << format->bits[3]) - 1;
-        dst->z = (float)((*src >> format->shift[3]) & mask) / mask;
-    }
-    else
-        dst->z = 1.0f;
+            memcpy(&tmp, src + format->shift[c] / 8,
+                    min(sizeof(DWORD), (format->shift[c] % 8 + format->bits[c] + 7) / 8));
 
-    if (format->bits[0])
-    {
-        mask = (1 << format->bits[0]) - 1;
-        dst->w = (float)((*src >> format->shift[0]) & mask) / mask;
+            if (format->type == FORMAT_ARGBF16)
+                *dst_component = float_16_to_32(tmp);
+            else if (format->type == FORMAT_ARGBF)
+                *dst_component = *(float *)&tmp;
+            else
+                *dst_component = (float)((tmp >> format->shift[c] % 8) & mask) / mask;
+        }
+        else
+            *dst_component = 1.0f;
     }
-    else
-        dst->w = 1.0f;
 }
 
-static void format_from_vec4(const struct pixel_format_desc *format, const struct vec4 *src, DWORD *dst)
+/* It doesn't work for components bigger than 32 bits. */
+static void format_from_vec4(const struct pixel_format_desc *format, const struct vec4 *src, BYTE *dst)
 {
-    *dst = 0;
-
-    if (format->bits[1])
-        *dst |= (DWORD)(src->x * ((1 << format->bits[1]) - 1) + 0.5f) << format->shift[1];
-    if (format->bits[2])
-        *dst |= (DWORD)(src->y * ((1 << format->bits[2]) - 1) + 0.5f) << format->shift[2];
-    if (format->bits[3])
-        *dst |= (DWORD)(src->z * ((1 << format->bits[3]) - 1) + 0.5f) << format->shift[3];
-    if (format->bits[0])
-        *dst |= (DWORD)(src->w * ((1 << format->bits[0]) - 1) + 0.5f) << format->shift[0];
+    DWORD v, mask32;
+    unsigned int c, i;
+
+    memset(dst, 0, format->bytes_per_pixel);
+
+    for (c = 0; c < 4; ++c)
+    {
+        static const unsigned int component_offsets[4] = {3, 0, 1, 2};
+        const float src_component = *((const float *)src + component_offsets[c]);
+
+        if (!format->bits[c])
+            continue;
+
+        mask32 = format->bits[c] == 32 ? ~0U : ((1 << format->bits[c]) - 1);
+
+        if (format->type == FORMAT_ARGBF16)
+            v = float_32_to_16(src_component);
+        else if (format->type == FORMAT_ARGBF)
+            v = *(DWORD *)&src_component;
+        else
+            v = (DWORD)(src_component * ((1 << format->bits[c]) - 1) + 0.5f);
+
+        for (i = format->shift[c] / 8 * 8; i < format->shift[c] + format->bits[c]; i += 8)
+        {
+            BYTE mask, byte;
+
+            if (format->shift[c] > i)
+            {
+                mask = mask32 << (format->shift[c] - i);
+                byte = (v << (format->shift[c] - i)) & mask;
+            }
+            else
+            {
+                mask = mask32 >> (i - format->shift[c]);
+                byte = (v >> (i - format->shift[c])) & mask;
+            }
+            dst[i / 8] |= byte;
+        }
+    }
 }
 
 /************************************************************
@@ -1500,7 +1496,7 @@ void convert_argb_pixels(const BYTE *src, UINT src_row_pitch, UINT src_slice_pit
 {
     struct argb_conversion_info conv_info, ck_conv_info;
     const struct pixel_format_desc *ck_format = NULL;
-    DWORD channels[4], pixel;
+    DWORD channels[4];
     UINT min_width, min_height, min_depth;
     UINT x, y, z;
 
@@ -1525,30 +1521,32 @@ void convert_argb_pixels(const BYTE *src, UINT src_row_pitch, UINT src_slice_pit
         for (y = 0; y < min_height; y++) {
             const BYTE *src_ptr = src_slice_ptr + y * src_row_pitch;
             BYTE *dst_ptr = dst_slice_ptr + y * dst_row_pitch;
-            DWORD val;
 
             for (x = 0; x < min_width; x++) {
-                /* extract source color components */
-                pixel = dword_from_bytes(src_ptr, src_format->bytes_per_pixel);
-
-                if (!src_format->to_rgba && !dst_format->from_rgba)
+                if (!src_format->to_rgba && !dst_format->from_rgba
+                        && src_format->bytes_per_pixel <= 4 && dst_format->bytes_per_pixel <= 4)
                 {
-                    get_relevant_argb_components(&conv_info, pixel, channels);
+                    DWORD val;
+
+                    get_relevant_argb_components(&conv_info, *(DWORD *)src_ptr, channels);
                     val = make_argb_color(&conv_info, channels);
 
                     if (color_key)
                     {
-                        get_relevant_argb_components(&ck_conv_info, pixel, channels);
-                        pixel = make_argb_color(&ck_conv_info, channels);
-                        if (pixel == color_key)
+                        DWORD ck_pixel;
+
+                        get_relevant_argb_components(&ck_conv_info, *(DWORD *)src_ptr, channels);
+                        ck_pixel = make_argb_color(&ck_conv_info, channels);
+                        if (ck_pixel == color_key)
                             val &= ~conv_info.destmask[0];
                     }
+                    memcpy(dst_ptr, &val, dst_format->bytes_per_pixel);
                 }
                 else
                 {
                     struct vec4 color, tmp;
 
-                    format_to_vec4(src_format, &pixel, &color);
+                    format_to_vec4(src_format, src_ptr, &color);
                     if (src_format->to_rgba)
                         src_format->to_rgba(&color, &tmp, palette);
                     else
@@ -1556,8 +1554,10 @@ void convert_argb_pixels(const BYTE *src, UINT src_row_pitch, UINT src_slice_pit
 
                     if (ck_format)
                     {
-                        format_from_vec4(ck_format, &tmp, &pixel);
-                        if (pixel == color_key)
+                        DWORD ck_pixel;
+
+                        format_from_vec4(ck_format, &tmp, (BYTE *)&ck_pixel);
+                        if (ck_pixel == color_key)
                             tmp.w = 0.0f;
                     }
 
@@ -1566,11 +1566,10 @@ void convert_argb_pixels(const BYTE *src, UINT src_row_pitch, UINT src_slice_pit
                     else
                         color = tmp;
 
-                    format_from_vec4(dst_format, &color, &val);
+                    format_from_vec4(dst_format, &color, dst_ptr);
                 }
 
-                dword_to_bytes(dst_ptr, val, dst_format->bytes_per_pixel);
-                src_ptr  +=  src_format->bytes_per_pixel;
+                src_ptr += src_format->bytes_per_pixel;
                 dst_ptr += dst_format->bytes_per_pixel;
             }
 
@@ -1600,7 +1599,7 @@ void point_filter_argb_pixels(const BYTE *src, UINT src_row_pitch, UINT src_slic
 {
     struct argb_conversion_info conv_info, ck_conv_info;
     const struct pixel_format_desc *ck_format = NULL;
-    DWORD channels[4], pixel;
+    DWORD channels[4];
     UINT x, y, z;
 
     ZeroMemory(channels, sizeof(channels));
@@ -1626,29 +1625,31 @@ void point_filter_argb_pixels(const BYTE *src, UINT src_row_pitch, UINT src_slic
             for (x = 0; x < dst_size->width; x++)
             {
                 const BYTE *src_ptr = src_row_ptr + (x * src_size->width / dst_size->width) * src_format->bytes_per_pixel;
-                DWORD val;
-
-                /* extract source color components */
-                pixel = dword_from_bytes(src_ptr, src_format->bytes_per_pixel);
 
-                if (!src_format->to_rgba && !dst_format->from_rgba)
+                if (!src_format->to_rgba && !dst_format->from_rgba
+                        && src_format->bytes_per_pixel <= 4 && dst_format->bytes_per_pixel <= 4)
                 {
-                    get_relevant_argb_components(&conv_info, pixel, channels);
+                    DWORD val;
+
+                    get_relevant_argb_components(&conv_info, *(DWORD *)src_ptr, channels);
                     val = make_argb_color(&conv_info, channels);
 
                     if (color_key)
                     {
-                        get_relevant_argb_components(&ck_conv_info, pixel, channels);
-                        pixel = make_argb_color(&ck_conv_info, channels);
-                        if (pixel == color_key)
+                        DWORD ck_pixel;
+
+                        get_relevant_argb_components(&ck_conv_info, *(DWORD *)src_ptr, channels);
+                        ck_pixel = make_argb_color(&ck_conv_info, channels);
+                        if (ck_pixel == color_key)
                             val &= ~conv_info.destmask[0];
                     }
+                    memcpy(dst_ptr, &val, dst_format->bytes_per_pixel);
                 }
                 else
                 {
                     struct vec4 color, tmp;
 
-                    format_to_vec4(src_format, &pixel, &color);
+                    format_to_vec4(src_format, src_ptr, &color);
                     if (src_format->to_rgba)
                         src_format->to_rgba(&color, &tmp, palette);
                     else
@@ -1656,8 +1657,10 @@ void point_filter_argb_pixels(const BYTE *src, UINT src_row_pitch, UINT src_slic
 
                     if (ck_format)
                     {
-                        format_from_vec4(ck_format, &tmp, &pixel);
-                        if (pixel == color_key)
+                        DWORD ck_pixel;
+
+                        format_from_vec4(ck_format, &tmp, (BYTE *)&ck_pixel);
+                        if (ck_pixel == color_key)
                             tmp.w = 0.0f;
                     }
 
@@ -1666,10 +1669,9 @@ void point_filter_argb_pixels(const BYTE *src, UINT src_row_pitch, UINT src_slic
                     else
                         color = tmp;
 
-                    format_from_vec4(dst_format, &color, &val);
+                    format_from_vec4(dst_format, &color, dst_ptr);
                 }
 
-                dword_to_bytes(dst_ptr, val, dst_format->bytes_per_pixel);
                 dst_ptr += dst_format->bytes_per_pixel;
             }
         }
-- 
1.8.3.2




More information about the wine-patches mailing list