ChangeLog: Fixes for memory alignment and endianess issues x11drv DIB functions. Description: Introduced byte-swapping and safe memory access in various places in x11drv DIB related functions. Added FIXME messages in not yet big-endian safe functions. Warren Baird : Warren_Baird@cimmetry.com diff -ur clean/wine/graphics/x11drv/dib.c wine/graphics/x11drv/dib.c --- clean/wine/graphics/x11drv/dib.c Wed Jan 29 15:31:02 2003 +++ wine/graphics/x11drv/dib.c Fri Jan 31 10:07:55 2003 @@ -400,6 +400,10 @@ DWORD* dstpixel; int x,y; +#ifdef WORDS_BIGENDIAN + FIXME("This code is not yet big-endian safe - expect corrupt images\n"); +#endif + for (y=0; y<height; y++) { srcpixel=srcbits; dstpixel=dstbits; @@ -432,6 +436,10 @@ DWORD* dstpixel; int x,y; +#ifdef WORDS_BIGENDIAN + FIXME("This code is not yet big-endian safe - expect corrupt images\n"); +#endif + for (y=0; y<height; y++) { srcpixel=srcbits; dstpixel=dstbits; @@ -464,6 +472,10 @@ DWORD* dstpixel; int x,y; +#ifdef WORDS_BIGENDIAN + FIXME("This code is not yet big-endian safe - expect corrupt images\n"); +#endif + for (y=0; y<height; y++) { srcpixel=srcbits; dstpixel=dstbits; @@ -498,6 +510,10 @@ BYTE* dstpixel; int x,y; +#ifdef WORDS_BIGENDIAN + FIXME("This code is not yet big-endian safe - expect corrupt images\n"); +#endif + for (y=0; y<height; y++) { srcpixel=srcbits; dstpixel=dstbits; @@ -525,6 +541,10 @@ BYTE* dstpixel; int x,y; +#ifdef WORDS_BIGENDIAN + FIXME("This code is not yet big-endian safe - expect corrupt images\n"); +#endif + for (y=0; y<height; y++) { srcpixel=srcbits; dstpixel=dstbits; @@ -552,6 +572,10 @@ DWORD* dstpixel; int x,y; +#ifdef WORDS_BIGENDIAN + FIXME("This code is not yet big-endian safe - expect corrupt images\n"); +#endif + for (y=0; y<height; y++) { srcpixel=srcbits; dstpixel=dstbits; @@ -578,6 +602,10 @@ DWORD* dstpixel; int x,y; +#ifdef WORDS_BIGENDIAN + FIXME("This code is not yet big-endian safe - expect corrupt images\n"); +#endif + for (y=0; y<height; y++) { srcpixel=srcbits; dstpixel=dstbits; @@ -610,6 +638,10 @@ DWORD* dstpixel; int x,y; +#ifdef WORDS_BIGENDIAN + FIXME("This code is not yet big-endian safe - expect corrupt images\n"); +#endif + /* Note, the source pixel value is shifted left by 16 bits so that * we know we will always have to shift right to extract the components. */ @@ -669,6 +701,10 @@ DWORD* dstpixel; int x,y; +#ifdef WORDS_BIGENDIAN + FIXME("This code is not yet big-endian safe - expect corrupt images\n"); +#endif + for (y=0; y<height; y++) { srcpixel=srcbits; dstpixel=dstbits; @@ -701,6 +737,10 @@ DWORD* dstpixel; int x,y; +#ifdef WORDS_BIGENDIAN + FIXME("This code is not yet big-endian safe - expect corrupt images\n"); +#endif + for (y=0; y<height; y++) { srcpixel=srcbits; dstpixel=dstbits; @@ -731,6 +771,10 @@ DWORD* dstpixel; int x,y; +#ifdef WORDS_BIGENDIAN + FIXME("This code is not yet big-endian safe - expect corrupt images\n"); +#endif + for (y=0; y<height; y++) { srcpixel=srcbits; dstpixel=dstbits; @@ -763,6 +807,10 @@ BYTE* dstpixel; int x,y; +#ifdef WORDS_BIGENDIAN + FIXME("This code is not yet big-endian safe - expect corrupt images\n"); +#endif + for (y=0; y<height; y++) { srcpixel=srcbits; dstpixel=dstbits; @@ -790,6 +838,10 @@ BYTE* dstpixel; int x,y; +#ifdef WORDS_BIGENDIAN + FIXME("This code is not yet big-endian safe - expect corrupt images\n"); +#endif + for (y=0; y<height; y++) { srcpixel=srcbits; dstpixel=dstbits; @@ -817,6 +869,10 @@ DWORD* dstpixel; int x,y; +#ifdef WORDS_BIGENDIAN + FIXME("This code is not yet big-endian safe - expect corrupt images\n"); +#endif + for (y=0; y<height; y++) { srcpixel=srcbits; dstpixel=dstbits; @@ -843,6 +899,10 @@ DWORD* dstpixel; int x,y; +#ifdef WORDS_BIGENDIAN + FIXME("This code is not yet big-endian safe - expect corrupt images\n"); +#endif + for (y=0; y<height; y++) { srcpixel=srcbits; dstpixel=dstbits; @@ -873,6 +933,10 @@ BYTE* dstpixel; int x,y; +#ifdef WORDS_BIGENDIAN + FIXME("This code is not yet big-endian safe - expect corrupt images\n"); +#endif + for (y=0; y<height; y++) { srcpixel=srcbits; dstpixel=dstbits; @@ -898,6 +962,10 @@ int x,y; int oddwidth; +#ifdef WORDS_BIGENDIAN + FIXME("This code is not yet big-endian safe - expect corrupt images\n"); +#endif + oddwidth=width & 3; width=width/4; for (y=0; y<height; y++) { @@ -949,6 +1017,10 @@ int x,y; int oddwidth; +#ifdef WORDS_BIGENDIAN + FIXME("This code is not yet big-endian safe - expect corrupt images\n"); +#endif + oddwidth=width & 3; width=width/4; for (y=0; y<height; y++) { @@ -1000,6 +1072,10 @@ int x,y; int oddwidth; +#ifdef WORDS_BIGENDIAN + FIXME("This code is not yet big-endian safe - expect corrupt images\n"); +#endif + oddwidth=width & 3; width=width/4; for (y=0; y<height; y++) { @@ -1051,6 +1127,10 @@ int x,y; int oddwidth; +#ifdef WORDS_BIGENDIAN + FIXME("This code is not yet big-endian safe - expect corrupt images\n"); +#endif + oddwidth=width & 3; width=width/4; for (y=0; y<height; y++) { @@ -1107,6 +1187,19 @@ srcpixel=srcbits; dstpixel=dstbits; for (x=0; x<width; x++) { +#ifdef WORDS_BIGENDIAN + /* Do 4 pixels at a time: 3 dwords in and 4 dwords out */ + DWORD srcval1,srcval2; + srcval1=srcpixel[0]; + dstpixel[0]=( srcval1 & 0xffffff00) ; /* h1, g1, l1 */ + srcval2=srcpixel[1]; + dstpixel[1]=( srcval1 & 0xff) << 24 | /* l2 */ + ( srcval2 & 0xffff0000) >> 8 ; /* h2, g2 */ + srcval1=srcpixel[2]; + dstpixel[2]=( srcval2 & 0x0000ffff) << 16 | /* g3, l3 */ + ( srcval1 & 0xff000000) >> 16; /* h3 */ + dstpixel[3]=( srcval1 & 0x00ffffff) << 8; /* h4, g4, l4 */ +#else /* Do 4 pixels at a time: 3 dwords in and 4 dwords out */ DWORD srcval1,srcval2; srcval1=srcpixel[0]; @@ -1118,16 +1211,31 @@ dstpixel[2]=( srcval2 >> 16) | /* g3, l3 */ ((srcval1 << 16) & 0x00ff0000); /* h3 */ dstpixel[3]=( srcval1 >> 8); /* h4, g4, l4 */ +#endif srcpixel+=3; dstpixel+=4; } /* And now up to 3 odd pixels */ + /* There are alignment problems here - be careful on systems that + need alignment */ + +#ifdef ALLOW_UNALIGNED_ACCESS for (x=0; x<oddwidth; x++) { DWORD srcval; srcval=*srcpixel; srcpixel=(LPDWORD)(((char*)srcpixel)+3); *dstpixel++=( srcval & 0x00ffffff); /* h, g, l */ } +#else + if (oddwidth > 0) { + for (x=0; x<oddwidth; x++) { + DWORD srcval; + memcpy(&srcval,srcpixel,4); + srcpixel=(LPDWORD)(((char*)srcpixel)+3); + *dstpixel++ = (srcval & 0xffffff00) ; + } + } +#endif srcbits = (char*)srcbits + srclinebytes; dstbits = (char*)dstbits + dstlinebytes; } @@ -1150,7 +1258,17 @@ for (x=0; x<width; x++) { /* Do 4 pixels at a time: 3 dwords in and 4 dwords out */ DWORD srcval1,srcval2; - +#ifdef WORDS_BIGENDIAN + srcval1=srcpixel[0]; + dstpixel[0]=((srcval1 >> 8) & 0xffffff) ; /* h1, g1, l1 */ + srcval2=srcpixel[1]; + dstpixel[1]=((srcval1 << 16) & 0xff0000) | /* h2 */ + ((srcval2 >> 16) & 0x00ffff); /* g2,l2 */ + srcval1=srcpixel[2]; + dstpixel[2]=((srcval2 << 8) & 0xffff00) | /* h3,g3 */ + ((srcval1 >> 24) & 0x0000ff); /* h3 */ + dstpixel[3]=( srcval1 & 0xffffff); /* h4, g4, l4 */ +#else srcval1=srcpixel[0]; dstpixel[0]=((srcval1 >> 16) & 0x0000ff) | /* h1 */ ( srcval1 & 0x00ff00) | /* g1 */ @@ -1166,10 +1284,12 @@ dstpixel[3]=((srcval1 >> 24) & 0x0000ff) | /* h4 */ ((srcval1 >> 8) & 0x00ff00) | /* g4 */ ((srcval1 << 8) & 0xff0000); /* l4 */ +#endif srcpixel+=3; dstpixel+=4; } /* And now up to 3 odd pixels */ +#ifdef ALLOW_UNALIGNED_ACCESS for (x=0; x<oddwidth; x++) { DWORD srcval; srcval=*srcpixel; @@ -1178,6 +1298,17 @@ ( srcval & 0x00ff00) | /* g */ ((srcval << 16) & 0xff0000); /* l */ } +#else + if (oddwidth > 0) { + for (x=0; x<oddwidth; x++) { + DWORD srcval; + memcpy(&srcval,srcpixel,sizeof(DWORD)); + srcpixel=(LPDWORD)(((char*)srcpixel)+3); + *dstpixel++ = ((srcval >> 8) & 0xffffff) ; + + } + } +#endif srcbits = (char*)srcbits + srclinebytes; dstbits = (char*)dstbits + dstlinebytes; } @@ -1193,6 +1324,10 @@ DWORD* dstpixel; int x,y; +#ifdef WORDS_BIGENDIAN + FIXME("This code is not yet big-endian safe - expect corrupt images\n"); +#endif + rLeftShift=X11DRV_DIB_MaskToShift(rdst); gLeftShift=X11DRV_DIB_MaskToShift(gdst); bLeftShift=X11DRV_DIB_MaskToShift(bdst); @@ -1220,6 +1355,10 @@ DWORD* dstpixel; int x,y; +#ifdef WORDS_BIGENDIAN + FIXME("This code is not yet big-endian safe - expect corrupt images\n"); +#endif + rLeftShift=X11DRV_DIB_MaskToShift(rdst); gLeftShift=X11DRV_DIB_MaskToShift(gdst); bLeftShift=X11DRV_DIB_MaskToShift(bdst); @@ -1249,6 +1388,10 @@ DWORD* dstpixel; int x,y; +#ifdef WORDS_BIGENDIAN + FIXME("This code is not yet big-endian safe - expect corrupt images\n"); +#endif + for (y=0; y<height; y++) { srcpixel=srcbits; dstpixel=dstbits; @@ -1276,6 +1419,10 @@ DWORD* dstpixel; int x,y; +#ifdef WORDS_BIGENDIAN + FIXME("This code is not yet big-endian safe - expect corrupt images\n"); +#endif + rRightShift=X11DRV_DIB_MaskToShift(rsrc); gRightShift=X11DRV_DIB_MaskToShift(gsrc); bRightShift=X11DRV_DIB_MaskToShift(bsrc); @@ -1305,6 +1452,10 @@ WORD* dstpixel; int x,y; +#ifdef WORDS_BIGENDIAN + FIXME("This code is not yet big-endian safe - expect corrupt images\n"); +#endif + for (y=0; y<height; y++) { srcpixel=srcbits; dstpixel=dstbits; @@ -1328,6 +1479,10 @@ WORD* dstpixel; int x,y; +#ifdef WORDS_BIGENDIAN + FIXME("This code is not yet big-endian safe - expect corrupt images\n"); +#endif + for (y=0; y<height; y++) { srcpixel=srcbits; dstpixel=dstbits; @@ -1351,6 +1506,10 @@ WORD* dstpixel; int x,y; +#ifdef WORDS_BIGENDIAN + FIXME("This code is not yet big-endian safe - expect corrupt images\n"); +#endif + for (y=0; y<height; y++) { srcpixel=srcbits; dstpixel=dstbits; @@ -1374,6 +1533,10 @@ WORD* dstpixel; int x,y; +#ifdef WORDS_BIGENDIAN + FIXME("This code is not yet big-endian safe - expect corrupt images\n"); +#endif + for (y=0; y<height; y++) { srcpixel=srcbits; dstpixel=dstbits; @@ -1401,6 +1564,10 @@ WORD* dstpixel; int x,y; +#ifdef WORDS_BIGENDIAN + FIXME("This code is not yet big-endian safe - expect corrupt images\n"); +#endif + /* Here is how we proceed. Assume we have rsrc=0x0000ff00 and our pixel * contains 0x11223344. * - first we shift 0x11223344 right by rRightShift to bring the most @@ -1448,6 +1615,9 @@ BYTE* dstbyte; int x,y; int oddwidth; +#ifndef ALLOW_UNALIGNED_ACCESS + BYTE oddbytes[9]; /* space for bytes at end of row */ +#endif oddwidth=width & 3; width=width/4; @@ -1455,6 +1625,18 @@ srcpixel=srcbits; dstpixel=dstbits; for (x=0; x<width; x++) { +#ifdef WORDS_BIGENDIAN + /* Do 4 pixels at a time: 4 dwords in and 3 dwords out */ + DWORD srcval; + DWORD tmppixel; + + srcval=((*srcpixel++) & 0xffffff00); /* h1, g1, l1*/ + *dstpixel++=srcval | (*srcpixel & 0xff000000) >> 24; /* h2 */ + srcval=(*srcpixel++ & 0x00ffff00) << 8; /* g2, l2 */ + *dstpixel++=srcval | ((*srcpixel & 0xffff0000) >> 16); /* h3, g3 */ + srcval=(*srcpixel++ & 0x0000ff00) << 16; /* l3 */ + *dstpixel++=srcval | ((*srcpixel++ & 0xffffff00) >> 8); /* h4, g4, l4 */ +#else /* Do 4 pixels at a time: 4 dwords in and 3 dwords out */ DWORD srcval; srcval=((*srcpixel++) & 0x00ffffff); /* h1, g1, l1*/ @@ -1463,8 +1645,14 @@ *dstpixel++=srcval | ((*srcpixel) << 16); /* h3, g3 */ srcval=((*srcpixel++ >> 16) & 0x000000ff); /* l3 */ *dstpixel++=srcval | ((*srcpixel++) << 8); /* h4, g4, l4 */ +#endif } /* And now up to 3 odd pixels */ + + /* There are alignment problems here - be careful on systems that + need alignment */ + +#ifdef ALLOW_UNALIGNED_ACCESS dstbyte=(BYTE*)dstpixel; for (x=0; x<oddwidth; x++) { DWORD srcval; @@ -1472,6 +1660,23 @@ *((WORD*)dstbyte)++=srcval; /* h, g */ *dstbyte++=srcval >> 16; /* l */ } +#else + + + /* fill in a temporary buffer with the pixels, and memcpy + it into the place we need it */ + + for (x=0; x<oddwidth; x++) { + srcpixel++; + + oddbytes[x*3 ] = (*srcpixel & 0xff000000) >> 24; + oddbytes[x*3+1] = (*srcpixel & 0x00ff0000) >> 16; + oddbytes[x*3+2] = (*srcpixel & 0x0000ff00) >> 8; + } + + memcpy((BYTE*)dstpixel,oddbytes,oddwidth*3); + +#endif srcbits = (char*)srcbits + srclinebytes; dstbits = (char*)dstbits + dstlinebytes; } @@ -1486,6 +1691,9 @@ BYTE* dstbyte; int x,y; int oddwidth; +#ifndef ALLOW_UNALIGNED_ACCESS + BYTE oddbytes[9]; /* space for bytes at end of row */ +#endif oddwidth=width & 3; width=width/4; @@ -1494,6 +1702,19 @@ dstpixel=dstbits; for (x=0; x<width; x++) { /* Do 4 pixels at a time: 4 dwords in and 3 dwords out */ +#ifdef WORDS_BIGENDIAN + DWORD srcval; + srcval= (*srcpixel++ & 0xffffff) << 8; /* h1, g1, l1 */ + *dstpixel++=srcval | + ((*srcpixel & 0xff0000) >> 16); /* h2 */ + srcval = (*srcpixel++ & 0x00ffff) << 16; /* g2, l2 */ + *dstpixel++=srcval | + ((*srcpixel & 0x00ffff00) >> 8); /* h3, g3 */ + + srcval= ((*srcpixel++ & 0x000000ff) << 24); /* l3 */ + *dstpixel++=srcval | + (*srcpixel++ & 0xffffff); /* h4, g4, l4 */ +#else DWORD srcval1,srcval2; srcval1=*srcpixel++; srcval2= ((srcval1 >> 16) & 0x000000ff) | /* h1 */ @@ -1514,8 +1735,13 @@ ((srcval1 >> 8) & 0x0000ff00) | /* h4 */ ((srcval1 << 8) & 0x00ff0000) | /* g4 */ ( srcval1 << 24); /* l4 */ +#endif } /* And now up to 3 odd pixels */ + /* There are alignment problems here - be careful on systems that + need alignment */ + +#ifdef ALLOW_UNALIGNED_ACCESS dstbyte=(BYTE*)dstpixel; for (x=0; x<oddwidth; x++) { DWORD srcval; @@ -1524,6 +1750,22 @@ (srcval & 0xff00); /* g */ *dstbyte++=srcval; /* l */ } +#else + /* fill in a temporary buffer with the pixels, and memcpy + it into the place we need it */ + + for (x=0; x<oddwidth; x++) { + DWORD srcval; + srcval=*srcpixel++; + + oddbytes[x*3 ] = (srcval & 0xff0000) >> 16; /* h */ + oddbytes[x*3+1] = (srcval & 0x00ff00) >> 8; /* g */ + oddbytes[x*3+2] = (srcval & 0x0000ff); /* l */ + } + + memcpy((BYTE*)dstpixel,oddbytes,oddwidth*3); + +#endif srcbits = (char*)srcbits + srclinebytes; dstbits = (char*)dstbits + dstlinebytes; } @@ -1539,6 +1781,10 @@ BYTE* dstpixel; int x,y; +#ifdef WORDS_BIGENDIAN + FIXME("This code is not yet big-endian safe - expect corrupt images\n"); +#endif + rRightShift=X11DRV_DIB_MaskToShift(rsrc); gRightShift=X11DRV_DIB_MaskToShift(gsrc); bRightShift=X11DRV_DIB_MaskToShift(bsrc); @@ -1568,6 +1814,10 @@ BYTE* dstpixel; int x,y; +#ifdef WORDS_BIGENDIAN + FIXME("This code is not yet big-endian safe - expect corrupt images\n"); +#endif + rRightShift=X11DRV_DIB_MaskToShift(rsrc); gRightShift=X11DRV_DIB_MaskToShift(gsrc); bRightShift=X11DRV_DIB_MaskToShift(bsrc); @@ -2812,9 +3062,15 @@ for (x=0; x<dstwidth; x++) { *dstbyte++=X11DRV_DIB_GetNearestIndex (colors, 256, +#ifdef WORDS_BIGENDIAN + srcbyte[3], + srcbyte[2], + srcbyte[1]); +#else srcbyte[0], srcbyte[1], srcbyte[2]); +#endif srcbyte+=bytes_per_pixel; } srcbits = (char*)srcbits - bmpImage->bytes_per_line;