qt-bugs@ issue : 11790 (part of) applied: no author: Lubos Lunak See 0005-qpixmap_mitshm.patch for details. --- work/qt-x11-free-3.3.8/src/kernel/qpixmap_x11.cpp +++ work/qt-x11-free-3.3.8/src/kernel/qpixmap_x11.cpp @@ -1123,9 +1123,6 @@ bool QPixmap::convertFromImage( const QI return FALSE; int bppc = xi->bits_per_pixel; - if ( bppc > 8 && xi->byte_order == LSBFirst ) - bppc++; - bool contig_bits = n_bits(red_mask) == rbits && n_bits(green_mask) == gbits && n_bits(blue_mask) == bbits; @@ -1174,32 +1171,70 @@ bool QPixmap::convertFromImage( const QI } init=TRUE; } + + enum { BPP8, + BPP16_8_3_M3, BPP16_7_2_M3, BPP16_MSB, BPP16_LSB, + BPP24_MSB, BPP24_LSB, + BPP32_16_8_0, BPP32_MSB, BPP32_LSB + } mode = BPP8; - for ( uint y=0; ybytes_per_line*y; - QRgb* p = (QRgb *)src; + if ( bppc > 8 && xi->byte_order == LSBFirst ) + bppc++; -#define GET_RGB \ - int r = tqRed ( *p ); \ - int g = tqGreen( *p ); \ - int b = tqBlue ( *p++ ); \ - r = red_shift > 0 \ - ? r << red_shift : r >> -red_shift; \ - g = green_shift > 0 \ - ? g << green_shift : g >> -green_shift; \ - b = blue_shift > 0 \ - ? b << blue_shift : b >> -blue_shift; + int wordsize; + bool bigendian; + tqSysInfo( &wordsize, &bigendian ); + bool same_msb_lsb = ( xi->byte_order == MSBFirst ) == ( bigendian ); + + if( bppc == 8 ) // 8 bit + mode = BPP8; + else if( bppc == 16 || bppc == 17 ) { // 16 bit MSB/LSB + if( red_shift == 8 && green_shift == 3 && blue_shift == -3 + && !d8 && same_msb_lsb ) + mode = BPP16_8_3_M3; + else if( red_shift == 7 && green_shift == 2 && blue_shift == -3 + && !d8 && same_msb_lsb ) + mode = BPP16_7_2_M3; + else + mode = bppc == 17 ? BPP16_LSB : BPP16_MSB; + } else if( bppc == 24 || bppc == 25 ) { // 24 bit MSB/LSB + mode = bppc == 25 ? BPP24_LSB : BPP24_MSB; + } else if( bppc == 32 || bppc == 33 ) { // 32 bit MSB/LSB + if( red_shift == 16 && green_shift == 8 && blue_shift == 0 + && !d8 && same_msb_lsb ) + mode = BPP32_16_8_0; + else + mode = bppc == 33 ? BPP32_LSB : BPP32_MSB; + } else + tqFatal("Logic error 3"); #define GET_PIXEL \ int pixel; \ if ( d8 ) pixel = pix[*src++]; \ else { \ - GET_RGB \ - pixel = (b & blue_mask)|(g & green_mask) | (r & red_mask) \ + int r = tqRed ( *p ); \ + int g = tqGreen( *p ); \ + int b = tqBlue ( *p++ ); \ + r = red_shift > 0 \ + ? r << red_shift : r >> -red_shift; \ + g = green_shift > 0 \ + ? g << green_shift : g >> -green_shift; \ + b = blue_shift > 0 \ + ? b << blue_shift : b >> -blue_shift; \ + pixel = (r & red_mask)|(g & green_mask) | (b & blue_mask) \ | ~(blue_mask | green_mask | red_mask); \ } +// optimized case - no d8 case, shift only once instead of twice, mask only once instead of twice, +// use direct values instead of variables, and use only one statement +// (*p >> 16), (*p >> 8 ) and (*p) are tqRed(),tqGreen() and tqBlue() without masking +// shifts have to be passed including the shift operator (e.g. '>>3'), because of the direction +#define GET_PIXEL_OPT(red_shift,green_shift,blue_shift,red_mask,green_mask,blue_mask) \ + int pixel = ((( *p >> 16 ) red_shift ) & red_mask ) \ + | ((( *p >> 8 ) green_shift ) & green_mask ) \ + | ((( *p ) blue_shift ) & blue_mask ); \ + ++p; + #define GET_PIXEL_DITHER_TC \ int r = tqRed ( *p ); \ int g = tqGreen( *p ); \ @@ -1220,91 +1255,177 @@ bool QPixmap::convertFromImage( const QI ? g << green_shift : g >> -green_shift; \ b = blue_shift > 0 \ ? b << blue_shift : b >> -blue_shift; \ - int pixel = (b & blue_mask)|(g & green_mask) | (r & red_mask); + int pixel = (r & red_mask)|(g & green_mask) | (b & blue_mask); - if ( dither_tc ) { - uint x; - switch ( bppc ) { - case 16: // 16 bit MSB - for ( x=0; x> 8); - *dst++ = pixel; - } +// again, optimized case +// can't be optimized that much :( +#define GET_PIXEL_DITHER_TC_OPT(red_shift,green_shift,blue_shift,red_mask,green_mask,blue_mask, \ + rbits,gbits,bbits) \ + const int thres = D[x%16][y%16]; \ + int r = tqRed ( *p ); \ + if ( r <= (255-(1<<(8-rbits))) && ((r< thres) \ + r += (1<<(8-rbits)); \ + int g = tqGreen( *p ); \ + if ( g <= (255-(1<<(8-gbits))) && ((g< thres) \ + g += (1<<(8-gbits)); \ + int b = tqBlue ( *p++ ); \ + if ( b <= (255-(1<<(8-bbits))) && ((b< thres) \ + b += (1<<(8-bbits)); \ + int pixel = (( r red_shift ) & red_mask ) \ + | (( g green_shift ) & green_mask ) \ + | (( b blue_shift ) & blue_mask ); + +#define CYCLE(body) \ + for ( uint y=0; ybytes_per_line*y; \ + QRgb* p = (QRgb *)src; \ + body \ + } + + if ( dither_tc ) { + switch ( mode ) { + case BPP16_8_3_M3: + CYCLE( + Q_INT16* dst16 = (Q_INT16*)dst; + for ( uint x=0; x>3,0xf800,0x7e0,0x1f,5,6,5) + *dst16++ = pixel; + } + ) break; - case 17: // 16 bit LSB - for ( x=0; x> 8; - } + case BPP16_7_2_M3: + CYCLE( + Q_INT16* dst16 = (Q_INT16*)dst; + for ( uint x=0; x>3,0x7c00,0x3e0,0x1f,5,5,5) + *dst16++ = pixel; + } + ) + break; + case BPP16_MSB: // 16 bit MSB + CYCLE( + for ( uint x=0; x> 8); + *dst++ = pixel; + } + ) + break; + case BPP16_LSB: // 16 bit LSB + CYCLE( + for ( uint x=0; x> 8; + } + ) break; default: tqFatal("Logic error"); } - } else { - uint x; - switch ( bppc ) { - case 8: // 8 bit - for ( x=0; x> 8); - *dst++ = pixel; - } + case BPP16_8_3_M3: + CYCLE( + Q_INT16* dst16 = (Q_INT16*)dst; + for ( uint x=0; x>3,0xf800,0x7e0,0x1f) + *dst16++ = pixel; + } + ) break; - case 17: // 16 bit LSB - for ( x=0; x> 8; - } + case BPP16_7_2_M3: + CYCLE( + Q_INT16* dst16 = (Q_INT16*)dst; + for ( uint x=0; x>3,0x7c00,0x3e0,0x1f) + *dst16++ = pixel; + } + ) break; - case 24: // 24 bit MSB - for ( x=0; x> 16; - *dst++ = pixel >> 8; - *dst++ = pixel; - } + case BPP16_MSB: // 16 bit MSB + CYCLE( + for ( uint x=0; x> 8); + *dst++ = pixel; + } + ) break; - case 25: // 24 bit LSB - for ( x=0; x> 8; - *dst++ = pixel >> 16; - } + case BPP16_LSB: // 16 bit LSB + CYCLE( + for ( uint x=0; x> 8; + } + ) break; - case 32: // 32 bit MSB - for ( x=0; x> 24; - *dst++ = pixel >> 16; - *dst++ = pixel >> 8; - *dst++ = pixel; - } + case BPP24_MSB: // 24 bit MSB + CYCLE( + for ( uint x=0; x> 16; + *dst++ = pixel >> 8; + *dst++ = pixel; + } + ) break; - case 33: // 32 bit LSB - for ( x=0; x> 8; - *dst++ = pixel >> 16; - *dst++ = pixel >> 24; - } + case BPP24_LSB: // 24 bit LSB + CYCLE( + for ( uint x=0; x> 8; + *dst++ = pixel >> 16; + } + ) break; - default: - tqFatal("Logic error 2"); - } - } - } - xi->data = (char *)newbits; + case BPP32_16_8_0: + CYCLE( + memcpy( dst, p, w * 4 ); + ) + break; + case BPP32_MSB: // 32 bit MSB + CYCLE( + for ( uint x=0; x> 24; + *dst++ = pixel >> 16; + *dst++ = pixel >> 8; + *dst++ = pixel; + } + ) + break; + case BPP32_LSB: // 32 bit LSB + CYCLE( + for ( uint x=0; x> 8; + *dst++ = pixel >> 16; + *dst++ = pixel >> 24; + } + ) + break; + default: + tqFatal("Logic error 2"); + } + } + xi->data = (char *)newbits; } if ( d == 8 && !trucol ) { // 8 bit pixmap @@ -1554,15 +1675,24 @@ bool QPixmap::convertFromImage( const QI if (image.depth() == 32) { const int *iptr = (const int *) image.bits(); - int max = w * h; - while (max--) - *aptr++ = *iptr++ >> 24; // squirt + if( axi->bytes_per_line == (int)w ) { + int max = w * h; + while (max--) + *aptr++ = *iptr++ >> 24; // squirt + } else { + for (uint i = 0; i < h; ++i ) { + for (uint j = 0; j < w; ++j ) + *aptr++ = *iptr++ >> 24; // squirt + aptr += ( axi->bytes_per_line - w ); + } + } } else if (image.depth() == 8) { const QRgb * const rgb = image.colorTable(); for (uint y = 0; y < h; ++y) { const uchar *iptr = image.scanLine(y); for (uint x = 0; x < w; ++x) *aptr++ = tqAlpha(rgb[*iptr++]); + aptr += ( axi->bytes_per_line - w ); } }