From 5380572057b0247b906c5a9f266aef0910a6a78a Mon Sep 17 00:00:00 2001 From: Henri Verbeet Date: Thu, 8 Mar 2012 20:27:12 +0100 Subject: [PATCH] d3dx9: Implement loading luminance/alpha data in D3DXLoadSurfaceFromMemory(). --- 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 ed46402ed3b..95006e46ae9 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 ca1699b9708..f436c533a0e 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) - /* make this pixel transparent */ - val &= ~conv_info.destmask[0]; + 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; + + 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) - /* make this pixel transparent */ - val &= ~conv_info.destmask[0]; + 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; + + 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 ddb54c35a36..0ed315c6a06 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 }, };