Rein Klazes : x11drv: Avoid unaligned 32 bit reads,
and reads beyond the input pixel
Alexandre Julliard
julliard at wine.codeweavers.com
Wed Mar 15 05:11:54 CST 2006
Module: wine
Branch: refs/heads/master
Commit: 883e0b0edc21d16da5eb2f6bf02d5a18ac31ce38
URL: http://source.winehq.org/git/?p=wine.git;a=commit;h=883e0b0edc21d16da5eb2f6bf02d5a18ac31ce38
Author: Rein Klazes <wijn at wanadoo.nl>
Date: Wed Mar 1 16:39:42 2006 +0100
x11drv: Avoid unaligned 32 bit reads, and reads beyond the input pixel
buffer in the convert_888_to_0888_* functions.
---
dlls/x11drv/dib_convert.c | 102 ++++++++++++++++++++++++++++++++++-----------
1 files changed, 78 insertions(+), 24 deletions(-)
diff --git a/dlls/x11drv/dib_convert.c b/dlls/x11drv/dib_convert.c
index b504843..347e1b3 100644
--- a/dlls/x11drv/dib_convert.c
+++ b/dlls/x11drv/dib_convert.c
@@ -821,18 +821,36 @@ static void convert_888_to_0888_asis(int
const DWORD* srcpixel;
DWORD* dstpixel;
int x,y;
- int oddwidth;
-
- oddwidth=width & 3;
- width=width/4;
+ int w1, w2, w3;
+
+ w1 = min( (INT_PTR)srcbits & 3, width);
+ w2 = ( width - w1) / 4;
+ w3 = ( width - w1) & 3;
for (y=0; y<height; y++) {
srcpixel=srcbits;
dstpixel=dstbits;
- for (x=0; x<width; x++) {
+ /* advance w1 pixels to make srcpixel 32 bit alignd */
+ srcpixel = (const DWORD*)((INT_PTR)srcpixel & ~3);
+ srcpixel += w1;
+ dstpixel += w1;
+ /* and do the w1 pixels */
+ x = w1;
+ if( x) {
+ dstpixel[ -1] = ( srcpixel[ -1] >> 8); /* h4, g4, l4 */
+ if( --x) {
+ dstpixel[ -2] = ( srcpixel[ -2] >> 16) | /* g3, l3 */
+ ((srcpixel[ -1] << 16) & 0x00ff0000); /* h3 */
+ if( --x) {
+ dstpixel[ -3] = ( srcpixel[ -3] >> 24) | /* l2 */
+ ((srcpixel[ -2] << 8) & 0x00ffff00); /* h2, g2 */
+ }
+ }
+ }
+ for (x=0; x < w2; x++) {
/* Do 4 pixels at a time: 3 dwords in and 4 dwords out */
DWORD srcval1,srcval2;
srcval1=srcpixel[0];
- dstpixel[0]=( srcval1 & 0x00ffffff); /* h1, g1, l1 */
+ dstpixel[0]=( srcval1 & 0x00ffffff); /* h1, g1, l1 */
srcval2=srcpixel[1];
dstpixel[1]=( srcval1 >> 24) | /* l2 */
((srcval2 << 8) & 0x00ffff00); /* h2, g2 */
@@ -843,12 +861,18 @@ static void convert_888_to_0888_asis(int
srcpixel+=3;
dstpixel+=4;
}
- /* And now up to 3 odd pixels */
- for (x=0; x<oddwidth; x++) {
- DWORD srcval;
- srcval=*srcpixel;
- srcpixel=(const DWORD*)(((const char*)srcpixel)+3);
- *dstpixel++=( srcval & 0x00ffffff); /* h, g, l */
+ /* do last w3 pixels */
+ x = w3;
+ if( x) {
+ dstpixel[0]=( srcpixel[0] & 0x00ffffff); /* h1, g1, l1 */
+ if( --x) {
+ dstpixel[1]=( srcpixel[0]>> 24) | /* l2 */
+ ((srcpixel[1]<< 8) & 0x00ffff00); /* h2, g2 */
+ if( --x) {
+ dstpixel[2]=( srcpixel[1]>> 16) | /* g3, l3 */
+ ((srcpixel[2]<< 16) & 0x00ff0000); /* h3 */
+ }
+ }
}
srcbits = (const char*)srcbits + srclinebytes;
dstbits = (char*)dstbits + dstlinebytes;
@@ -862,14 +886,36 @@ static void convert_888_to_0888_reverse(
const DWORD* srcpixel;
DWORD* dstpixel;
int x,y;
- int oddwidth;
+ int w1, w2, w3;
- oddwidth=width & 3;
- width=width/4;
+ w1 = min( (INT_PTR)srcbits & 3, width);
+ w2 = ( width - w1) / 4;
+ w3 = ( width - w1) & 3;
for (y=0; y<height; y++) {
srcpixel=srcbits;
dstpixel=dstbits;
- for (x=0; x<width; x++) {
+ /* advance w1 pixels to make srcpixel 32 bit alignd */
+ srcpixel = (const DWORD*)((INT_PTR)srcpixel & ~3);
+ srcpixel += w1;
+ dstpixel += w1;
+ /* and do the w1 pixels */
+ x = w1;
+ if( x) {
+ dstpixel[ -1]=((srcpixel[ -1] >> 24) & 0x0000ff) | /* h4 */
+ ((srcpixel[ -1] >> 8) & 0x00ff00) | /* g4 */
+ ((srcpixel[ -1] << 8) & 0xff0000); /* l4 */
+ if( --x) {
+ dstpixel[ -2]=( srcpixel[ -2] & 0xff0000) | /* l3 */
+ ((srcpixel[ -2] >> 16) & 0x00ff00) | /* g3 */
+ ( srcpixel[ -1] & 0x0000ff); /* h3 */
+ if( --x) {
+ dstpixel[ -3]=((srcpixel[ -3] >> 8) & 0xff0000) | /* l2 */
+ ((srcpixel[ -2] << 8) & 0x00ff00) | /* g2 */
+ ((srcpixel[ -2] >> 8) & 0x0000ff); /* h2 */
+ }
+ }
+ }
+ for (x=0; x < w2; x++) {
/* Do 4 pixels at a time: 3 dwords in and 4 dwords out */
DWORD srcval1,srcval2;
@@ -891,14 +937,22 @@ static void convert_888_to_0888_reverse(
srcpixel+=3;
dstpixel+=4;
}
- /* And now up to 3 odd pixels */
- for (x=0; x<oddwidth; x++) {
- DWORD srcval;
- srcval=*srcpixel;
- srcpixel=(const DWORD*)(((const char*)srcpixel)+3);
- *dstpixel++=((srcval >> 16) & 0x0000ff) | /* h */
- ( srcval & 0x00ff00) | /* g */
- ((srcval << 16) & 0xff0000); /* l */
+ /* do last w3 pixels */
+ x = w3;
+ if( x) {
+ dstpixel[0]=((srcpixel[0] >> 16) & 0x0000ff) | /* h1 */
+ ( srcpixel[0] & 0x00ff00) | /* g1 */
+ ((srcpixel[0] << 16) & 0xff0000); /* l1 */
+ if( --x) {
+ dstpixel[1]=((srcpixel[0] >> 8) & 0xff0000) | /* l2 */
+ ((srcpixel[1] << 8) & 0x00ff00) | /* g2 */
+ ((srcpixel[1] >> 8) & 0x0000ff); /* h2 */
+ if( --x) {
+ dstpixel[2]=( srcpixel[1] & 0xff0000) | /* l3 */
+ ((srcpixel[1] >> 16) & 0x00ff00) | /* g3 */
+ ( srcpixel[2] & 0x0000ff); /* h3 */
+ }
+ }
}
srcbits = (const char*)srcbits + srclinebytes;
dstbits = (char*)dstbits + dstlinebytes;
More information about the wine-cvs
mailing list