d3dx9: Fix memory access for images with less than 4 bytes per pixel (Valgrind).

This commit is contained in:
Matteo Bruni 2011-02-16 02:39:21 +01:00 committed by Alexandre Julliard
parent b6990fa77a
commit 85a578f782
1 changed files with 73 additions and 28 deletions

View File

@ -598,6 +598,39 @@ static void init_argb_conversion_info(CONST PixelFormatDesc *srcformat, CONST Pi
} }
} }
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);
fixme_once = TRUE;
}
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);
fixme_once = TRUE;
}
ZeroMemory(dst, bytes_per_pixel);
bytes_per_pixel = sizeof(DWORD);
}
memcpy(dst, &dword, bytes_per_pixel);
}
/************************************************************ /************************************************************
* get_relevant_argb_components * get_relevant_argb_components
* *
@ -618,20 +651,21 @@ static void get_relevant_argb_components(CONST struct argb_conversion_info *info
* Recombines the output of get_relevant_argb_components and converts * Recombines the output of get_relevant_argb_components and converts
* it to the destination format. * it to the destination format.
*/ */
static void make_argb_color(CONST struct argb_conversion_info *info, CONST DWORD *in, DWORD *out) static DWORD make_argb_color(CONST struct argb_conversion_info *info, CONST DWORD *in)
{ {
UINT i; UINT i;
*out = 0; DWORD val = 0;
for(i = 0;i < 4;i++) { for(i = 0;i < 4;i++) {
if(info->process_channel[i]) { if(info->process_channel[i]) {
/* necessary to make sure that e.g. an X4R4G4B4 white maps to an R8G8B8 white instead of 0xf0f0f0 */ /* necessary to make sure that e.g. an X4R4G4B4 white maps to an R8G8B8 white instead of 0xf0f0f0 */
signed int shift; signed int shift;
for(shift = info->destshift[i]; shift > info->destformat->shift[i]; shift -= info->srcformat->bits[i]) *out |= in[i] << shift; for(shift = info->destshift[i]; shift > info->destformat->shift[i]; shift -= info->srcformat->bits[i]) val |= in[i] << shift;
*out |= (in[i] >> (info->destformat->shift[i] - shift)) << info->destformat->shift[i]; val |= (in[i] >> (info->destformat->shift[i] - shift)) << info->destformat->shift[i];
} }
} }
*out |= info->channelmask; /* new channels are set to their maximal value */ val |= info->channelmask; /* new channels are set to their maximal value */
return val;
} }
/************************************************************ /************************************************************
@ -668,23 +702,29 @@ static void copy_simple_data(CONST BYTE *src, UINT srcpitch, POINT srcsize,
} }
for(y = 0;y < minheight;y++) { for(y = 0;y < minheight;y++) {
const BYTE *srcptr = src + y * srcpitch; const BYTE *srcptr = src + y * srcpitch;
BYTE *destptr = dest + y * destpitch; BYTE *destptr = dest + y * destpitch;
DWORD val = 0;
for(x = 0;x < minwidth;x++) { for(x = 0;x < minwidth;x++) {
/* extract source color components */ /* extract source color components */
if(srcformat->type == FORMAT_ARGB) get_relevant_argb_components(&conv_info, *(const DWORD*)srcptr, channels); if(srcformat->type == FORMAT_ARGB) {
pixel = dword_from_bytes(srcptr, srcformat->bytes_per_pixel);
/* recombine the components */ get_relevant_argb_components(&conv_info, pixel, channels);
if(destformat->type == FORMAT_ARGB) make_argb_color(&conv_info, channels, (DWORD*)destptr);
if(colorkey) {
get_relevant_argb_components(&ck_conv_info, *(const DWORD*)srcptr, channels);
make_argb_color(&ck_conv_info, channels, &pixel);
if(pixel == colorkey)
/* make this pixel transparent */
*(DWORD *)destptr &= ~conv_info.destmask[0];
} }
/* recombine the components */
if(destformat->type == FORMAT_ARGB) 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];
}
dword_to_bytes(destptr, val, destformat->bytes_per_pixel);
srcptr += srcformat->bytes_per_pixel; srcptr += srcformat->bytes_per_pixel;
destptr += destformat->bytes_per_pixel; destptr += destformat->bytes_per_pixel;
} }
@ -732,21 +772,26 @@ static void point_filter_simple_data(CONST BYTE *src, UINT srcpitch, POINT srcsi
for(x = 0;x < destsize.x;x++) { for(x = 0;x < destsize.x;x++) {
const BYTE *srcptr = bufptr + (x * srcsize.x / destsize.x) * srcformat->bytes_per_pixel; const BYTE *srcptr = bufptr + (x * srcsize.x / destsize.x) * srcformat->bytes_per_pixel;
DWORD val = 0;
/* extract source color components */ /* extract source color components */
if(srcformat->type == FORMAT_ARGB) get_relevant_argb_components(&conv_info, *(const DWORD*)srcptr, channels); if(srcformat->type == FORMAT_ARGB) {
pixel = dword_from_bytes(srcptr, srcformat->bytes_per_pixel);
/* recombine the components */ get_relevant_argb_components(&conv_info, pixel, channels);
if(destformat->type == FORMAT_ARGB) make_argb_color(&conv_info, channels, (DWORD*)destptr);
if(colorkey) {
get_relevant_argb_components(&ck_conv_info, *(const DWORD*)srcptr, channels);
make_argb_color(&ck_conv_info, channels, &pixel);
if(pixel == colorkey)
/* make this pixel transparent */
*(DWORD *)destptr &= ~conv_info.destmask[0];
} }
/* recombine the components */
if(destformat->type == FORMAT_ARGB) 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];
}
dword_to_bytes(destptr, val, destformat->bytes_per_pixel);
destptr += destformat->bytes_per_pixel; destptr += destformat->bytes_per_pixel;
} }
} }