[PATCH 1/5] d3dx9: Implement loading luminance/alpha data in D3DXLoadSurfaceFromMemory().

Henri Verbeet hverbeet at codeweavers.com
Thu Mar 8 13:27:12 CST 2012


---
 dlls/d3dx9_36/d3dx9_36_private.h |    7 ++
 dlls/d3dx9_36/surface.c          |  167 ++++++++++++++++++++++++++++++-------
 dlls/d3dx9_36/util.c             |   53 ++++++++-----
 3 files changed, 176 insertions(+), 51 deletions(-)

diff --git a/dlls/d3dx9_36/d3dx9_36_private.h b/dlls/d3dx9_36/d3dx9_36_private.h
index ed46402..95006e4 100644
--- a/dlls/d3dx9_36/d3dx9_36_private.h
+++ b/dlls/d3dx9_36/d3dx9_36_private.h
@@ -32,6 +32,11 @@
 
 #define ARRAY_SIZE(array) (sizeof(array)/sizeof(*array))
 
+struct vec4
+{
+    float x, y, z, w;
+};
+
 /* for internal use */
 typedef enum _FormatType {
     FORMAT_ARGB,   /* unsigned */
@@ -44,6 +49,8 @@ typedef struct _PixelFormatDesc {
     BYTE shift[4];
     UINT bytes_per_pixel;
     FormatType type;
+    void (*from_rgba)(const struct vec4 *src, struct vec4 *dst);
+    void (*to_rgba)(const struct vec4 *src, struct vec4 *dst);
 } PixelFormatDesc;
 
 HRESULT map_view_of_file(LPCWSTR filename, LPVOID *buffer, DWORD *length) DECLSPEC_HIDDEN;
diff --git a/dlls/d3dx9_36/surface.c b/dlls/d3dx9_36/surface.c
index ca1699b..f436c53 100644
--- a/dlls/d3dx9_36/surface.c
+++ b/dlls/d3dx9_36/surface.c
@@ -670,6 +670,57 @@ static DWORD make_argb_color(CONST struct argb_conversion_info *info, CONST DWOR
     return val;
 }
 
+static void format_to_vec4(const PixelFormatDesc *format, const DWORD *src, struct vec4 *dst)
+{
+    DWORD mask;
+
+    if (format->bits[1])
+    {
+        mask = (1 << format->bits[1]) - 1;
+        dst->x = (float)((*src >> format->shift[1]) & mask) / mask;
+    }
+    else
+        dst->x = 1.0f;
+
+    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[3])
+    {
+        mask = (1 << format->bits[3]) - 1;
+        dst->z = (float)((*src >> format->shift[3]) & mask) / mask;
+    }
+    else
+        dst->z = 1.0f;
+
+    if (format->bits[0])
+    {
+        mask = (1 << format->bits[0]) - 1;
+        dst->w = (float)((*src >> format->shift[0]) & mask) / mask;
+    }
+    else
+        dst->w = 1.0f;
+}
+
+static void format_from_vec4(const PixelFormatDesc *format, const struct vec4 *src, DWORD *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];
+}
+
 /************************************************************
  * copy_simple_data
  *
@@ -685,6 +736,7 @@ static void copy_simple_data(CONST BYTE *src, UINT srcpitch, POINT srcsize,
                              D3DCOLOR colorkey)
 {
     struct argb_conversion_info conv_info, ck_conv_info;
+    const PixelFormatDesc *ck_format = NULL;
     DWORD channels[4], pixel;
     UINT minwidth, minheight;
     UINT x, y;
@@ -695,33 +747,58 @@ static void copy_simple_data(CONST BYTE *src, UINT srcpitch, POINT srcsize,
     minwidth  = (srcsize.x < destsize.x) ? srcsize.x : destsize.x;
     minheight = (srcsize.y < destsize.y) ? srcsize.y : destsize.y;
 
-    if(colorkey) {
-        /* color keys are always represented in D3DFMT_A8R8G8B8 format */
-        const PixelFormatDesc *ckformatdesc;
-
-        ckformatdesc = get_format_info(D3DFMT_A8R8G8B8);
-        init_argb_conversion_info(srcformat, ckformatdesc, &ck_conv_info);
+    if (colorkey)
+    {
+        /* Color keys are always represented in D3DFMT_A8R8G8B8 format. */
+        ck_format = get_format_info(D3DFMT_A8R8G8B8);
+        init_argb_conversion_info(srcformat, ck_format, &ck_conv_info);
     }
 
     for(y = 0;y < minheight;y++) {
         const BYTE *srcptr = src + y * srcpitch;
         BYTE *destptr = dest + y * destpitch;
-        DWORD val = 0;
+        DWORD val;
 
         for(x = 0;x < minwidth;x++) {
             /* extract source color components */
             pixel = dword_from_bytes(srcptr, srcformat->bytes_per_pixel);
-            get_relevant_argb_components(&conv_info, pixel, channels);
 
-            /* recombine the components */
-            val = make_argb_color(&conv_info, channels);
+            if (!srcformat->to_rgba && !destformat->from_rgba)
+            {
+                get_relevant_argb_components(&conv_info, pixel, channels);
+                val = make_argb_color(&conv_info, channels);
+
+                if (colorkey)
+                {
+                    get_relevant_argb_components(&ck_conv_info, pixel, channels);
+                    pixel = make_argb_color(&ck_conv_info, channels);
+                    if (pixel == colorkey)
+                        val &= ~conv_info.destmask[0];
+                }
+            }
+            else
+            {
+                struct vec4 color, tmp;
+
+                format_to_vec4(srcformat, &pixel, &color);
+                if (srcformat->to_rgba)
+                    srcformat->to_rgba(&color, &tmp);
+                else
+                    tmp = color;
+
+                if (ck_format)
+                {
+                    format_from_vec4(ck_format, &tmp, &pixel);
+                    if (pixel == colorkey)
+                        tmp.w = 0.0f;
+                }
+
+                if (destformat->from_rgba)
+                    destformat->from_rgba(&tmp, &color);
+                else
+                    color = tmp;
 
-            if(colorkey) {
-                get_relevant_argb_components(&ck_conv_info, pixel, channels);
-                pixel = make_argb_color(&ck_conv_info, channels);
-                if(pixel == colorkey)
-                    /* make this pixel transparent */
-                    val &= ~conv_info.destmask[0];
+                format_from_vec4(destformat, &color, &val);
             }
 
             dword_to_bytes(destptr, val, destformat->bytes_per_pixel);
@@ -751,6 +828,7 @@ static void point_filter_simple_data(CONST BYTE *src, UINT srcpitch, POINT srcsi
                                      D3DCOLOR colorkey)
 {
     struct argb_conversion_info conv_info, ck_conv_info;
+    const PixelFormatDesc *ck_format = NULL;
     DWORD channels[4], pixel;
 
     UINT x, y;
@@ -758,12 +836,11 @@ static void point_filter_simple_data(CONST BYTE *src, UINT srcpitch, POINT srcsi
     ZeroMemory(channels, sizeof(channels));
     init_argb_conversion_info(srcformat, destformat, &conv_info);
 
-    if(colorkey) {
-        /* color keys are always represented in D3DFMT_A8R8G8B8 format */
-        const PixelFormatDesc *ckformatdesc;
-
-        ckformatdesc = get_format_info(D3DFMT_A8R8G8B8);
-        init_argb_conversion_info(srcformat, ckformatdesc, &ck_conv_info);
+    if (colorkey)
+    {
+        /* Color keys are always represented in D3DFMT_A8R8G8B8 format. */
+        ck_format = get_format_info(D3DFMT_A8R8G8B8);
+        init_argb_conversion_info(srcformat, ck_format, &ck_conv_info);
     }
 
     for(y = 0;y < destsize.y;y++) {
@@ -772,21 +849,47 @@ static void point_filter_simple_data(CONST BYTE *src, UINT srcpitch, POINT srcsi
 
         for(x = 0;x < destsize.x;x++) {
             const BYTE *srcptr = bufptr + (x * srcsize.x / destsize.x) * srcformat->bytes_per_pixel;
-            DWORD val = 0;
+            DWORD val;
 
             /* extract source color components */
             pixel = dword_from_bytes(srcptr, srcformat->bytes_per_pixel);
-            get_relevant_argb_components(&conv_info, pixel, channels);
 
-            /* recombine the components */
-            val = make_argb_color(&conv_info, channels);
+            if (!srcformat->to_rgba && !destformat->from_rgba)
+            {
+                get_relevant_argb_components(&conv_info, pixel, channels);
+                val = make_argb_color(&conv_info, channels);
+
+                if (colorkey)
+                {
+                    get_relevant_argb_components(&ck_conv_info, pixel, channels);
+                    pixel = make_argb_color(&ck_conv_info, channels);
+                    if (pixel == colorkey)
+                        val &= ~conv_info.destmask[0];
+                }
+            }
+            else
+            {
+                struct vec4 color, tmp;
+
+                format_to_vec4(srcformat, &pixel, &color);
+                if (srcformat->to_rgba)
+                    srcformat->to_rgba(&color, &tmp);
+                else
+                    tmp = color;
+
+                if (ck_format)
+                {
+                    format_from_vec4(ck_format, &tmp, &pixel);
+                    if (pixel == colorkey)
+                        tmp.w = 0.0f;
+                }
+
+                if (destformat->from_rgba)
+                    destformat->from_rgba(&tmp, &color);
+                else
+                    color = tmp;
 
-            if(colorkey) {
-                get_relevant_argb_components(&ck_conv_info, pixel, channels);
-                pixel = make_argb_color(&ck_conv_info, channels);
-                if(pixel == colorkey)
-                    /* make this pixel transparent */
-                    val &= ~conv_info.destmask[0];
+                format_from_vec4(destformat, &color, &val);
             }
 
             dword_to_bytes(destptr, val, destformat->bytes_per_pixel);
diff --git a/dlls/d3dx9_36/util.c b/dlls/d3dx9_36/util.c
index ddb54c3..0ed315c 100644
--- a/dlls/d3dx9_36/util.c
+++ b/dlls/d3dx9_36/util.c
@@ -22,6 +22,20 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(d3dx);
 
+static void la_from_rgba(const struct vec4 *rgba, struct vec4 *la)
+{
+    la->x = rgba->x * 0.2125f + rgba->y * 0.7154f + rgba->z * 0.0721f;
+    la->w = rgba->w;
+}
+
+static void la_to_rgba(const struct vec4 *la, struct vec4 *rgba)
+{
+    rgba->x = la->x;
+    rgba->y = la->x;
+    rgba->z = la->x;
+    rgba->w = la->w;
+}
+
 /************************************************************
  * pixel format table providing info about number of bytes per pixel,
  * number of bits per channel and format type.
@@ -30,25 +44,26 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3dx);
  */
 static const PixelFormatDesc formats[] =
 {
-   /* format                    bits per channel        shifts per channel   bpp   type        */
-    { D3DFMT_R8G8B8,          {  0,   8,   8,   8 },  {  0,  16,   8,   0 },   3,  FORMAT_ARGB },
-    { D3DFMT_A8R8G8B8,        {  8,   8,   8,   8 },  { 24,  16,   8,   0 },   4,  FORMAT_ARGB },
-    { D3DFMT_X8R8G8B8,        {  0,   8,   8,   8 },  {  0,  16,   8,   0 },   4,  FORMAT_ARGB },
-    { D3DFMT_A8B8G8R8,        {  8,   8,   8,   8 },  { 24,   0,   8,  16 },   4,  FORMAT_ARGB },
-    { D3DFMT_X8B8G8R8,        {  0,   8,   8,   8 },  {  0,   0,   8,  16 },   4,  FORMAT_ARGB },
-    { D3DFMT_R5G6B5,          {  0,   5,   6,   5 },  {  0,  11,   5,   0 },   2,  FORMAT_ARGB },
-    { D3DFMT_X1R5G5B5,        {  0,   5,   5,   5 },  {  0,  10,   5,   0 },   2,  FORMAT_ARGB },
-    { D3DFMT_A1R5G5B5,        {  1,   5,   5,   5 },  { 15,  10,   5,   0 },   2,  FORMAT_ARGB },
-    { D3DFMT_R3G3B2,          {  0,   3,   3,   2 },  {  0,   5,   2,   0 },   1,  FORMAT_ARGB },
-    { D3DFMT_A8R3G3B2,        {  8,   3,   3,   2 },  {  8,   5,   2,   0 },   2,  FORMAT_ARGB },
-    { D3DFMT_A4R4G4B4,        {  4,   4,   4,   4 },  { 12,   8,   4,   0 },   2,  FORMAT_ARGB },
-    { D3DFMT_X4R4G4B4,        {  0,   4,   4,   4 },  {  0,   8,   4,   0 },   2,  FORMAT_ARGB },
-    { D3DFMT_A2R10G10B10,     {  2,  10,  10,  10 },  { 30,  20,  10,   0 },   4,  FORMAT_ARGB },
-    { D3DFMT_A2B10G10R10,     {  2,  10,  10,  10 },  { 30,   0,  10,  20 },   4,  FORMAT_ARGB },
-    { D3DFMT_G16R16,          {  0,  16,  16,   0 },  {  0,   0,  16,   0 },   4,  FORMAT_ARGB },
-    { D3DFMT_A8,              {  8,   0,   0,   0 },  {  0,   0,   0,   0 },   1,  FORMAT_ARGB },
-
-    { D3DFMT_UNKNOWN,         {  0,   0,   0,   0 },  {  0,   0,   0,   0 },   0,  FORMAT_UNKNOWN }, /* marks last element */
+    /* format            bpc              shifts            bpp type            from_rgba     to_rgba */
+    {D3DFMT_R8G8B8,      {0,  8,  8,  8}, { 0, 16,  8,  0}, 3,  FORMAT_ARGB,    NULL,         NULL      },
+    {D3DFMT_A8R8G8B8,    {8,  8,  8,  8}, {24, 16,  8,  0}, 4,  FORMAT_ARGB,    NULL,         NULL      },
+    {D3DFMT_X8R8G8B8,    {0,  8,  8,  8}, { 0, 16,  8,  0}, 4,  FORMAT_ARGB,    NULL,         NULL      },
+    {D3DFMT_A8B8G8R8,    {8,  8,  8,  8}, {24,  0,  8, 16}, 4,  FORMAT_ARGB,    NULL,         NULL      },
+    {D3DFMT_X8B8G8R8,    {0,  8,  8,  8}, { 0,  0,  8, 16}, 4,  FORMAT_ARGB,    NULL,         NULL      },
+    {D3DFMT_R5G6B5,      {0,  5,  6,  5}, { 0, 11,  5,  0}, 2,  FORMAT_ARGB,    NULL,         NULL      },
+    {D3DFMT_X1R5G5B5,    {0,  5,  5,  5}, { 0, 10,  5,  0}, 2,  FORMAT_ARGB,    NULL,         NULL      },
+    {D3DFMT_A1R5G5B5,    {1,  5,  5,  5}, {15, 10,  5,  0}, 2,  FORMAT_ARGB,    NULL,         NULL      },
+    {D3DFMT_R3G3B2,      {0,  3,  3,  2}, { 0,  5,  2,  0}, 1,  FORMAT_ARGB,    NULL,         NULL      },
+    {D3DFMT_A8R3G3B2,    {8,  3,  3,  2}, { 8,  5,  2,  0}, 2,  FORMAT_ARGB,    NULL,         NULL      },
+    {D3DFMT_A4R4G4B4,    {4,  4,  4,  4}, {12,  8,  4,  0}, 2,  FORMAT_ARGB,    NULL,         NULL      },
+    {D3DFMT_X4R4G4B4,    {0,  4,  4,  4}, { 0,  8,  4,  0}, 2,  FORMAT_ARGB,    NULL,         NULL      },
+    {D3DFMT_A2R10G10B10, {2, 10, 10, 10}, {30, 20, 10,  0}, 4,  FORMAT_ARGB,    NULL,         NULL      },
+    {D3DFMT_A2B10G10R10, {2, 10, 10, 10}, {30,  0, 10, 20}, 4,  FORMAT_ARGB,    NULL,         NULL      },
+    {D3DFMT_G16R16,      {0, 16, 16,  0}, { 0,  0, 16,  0}, 4,  FORMAT_ARGB,    NULL,         NULL      },
+    {D3DFMT_A8,          {8,  0,  0,  0}, { 0,  0,  0,  0}, 1,  FORMAT_ARGB,    NULL,         NULL      },
+    {D3DFMT_A8L8,        {8,  8,  0,  0}, { 8,  0,  0,  0}, 2,  FORMAT_ARGB,    la_from_rgba, la_to_rgba},
+    /* marks last element */
+    {D3DFMT_UNKNOWN,     {0,  0,  0,  0}, { 0,  0,  0,  0}, 0,  FORMAT_UNKNOWN, NULL,         NULL      },
 };
 
 
-- 
1.7.3.4




More information about the wine-patches mailing list