#! /bin/sh -e ## 24_qtc_qscrollview.dpatch by Germain Garand ## ## All lines beginning with `## DP:' are a description of the patch. ## DP: fix the qscrollview stuff if [ $# -lt 1 ]; then echo "`basename $0`: script expects -patch|-unpatch as argument" >&2 exit 1 fi [ -f debian/patches/00patch-opts ] && . debian/patches/00patch-opts patch_opts="${patch_opts:--f --no-backup-if-mismatch} ${2:+-d $2}" case "$1" in -patch) patch -p1 ${patch_opts} < $0;; -unpatch) patch -R -p1 ${patch_opts} < $0;; *) echo "`basename $0`: script expects -patch|-unpatch as argument" >&2 exit 1;; esac exit 0 @DPATCH@ --- qt.orig/src/kernel/qpixmap_x11.cpp +++ qt.patched/src/kernel/qpixmap_x11.cpp @@ -37,7 +37,19 @@ // NOT REVISED +#include "qplatformdefs.h" + +#if defined(Q_OS_WIN32) && defined(QT_MITSHM) +#undef QT_MITSHM +#endif + +#ifdef QT_MITSHM + +// Use the MIT Shared Memory extension for pixmap<->image conversions +#define QT_MITSHM_CONVERSIONS + // Uncomment the next line to enable the MIT Shared Memory extension +// for QPixmap::xForm() // // WARNING: This has some problems: // @@ -45,14 +57,13 @@ // 2. Qt does not handle the ShmCompletion message, so you will // get strange effects if you xForm() repeatedly. // -// #define QT_MITSHM +// #define QT_MITSHM_XFORM -#if defined(Q_OS_WIN32) && defined(QT_MITSHM) -#undef QT_MITSHM +#else +#undef QT_MITSHM_CONVERSIONS +#undef QT_MITSHM_XFORM #endif -#include "qplatformdefs.h" - #include "qbitmap.h" #include "qpaintdevicemetrics.h" #include "qimage.h" @@ -91,7 +102,7 @@ inline static void qSafeXDestroyImage( X MIT Shared Memory Extension support: makes xForm noticeably (~20%) faster. *****************************************************************************/ -#if defined(QT_MITSHM) +#if defined(QT_MITSHM_XFORM) static bool xshminit = FALSE; static XShmSegmentInfo xshminfo; @@ -173,8 +184,100 @@ static bool qt_create_mitshm_buffer( con // return FALSE; // } -#endif // QT_MITSHM +#endif // QT_MITSHM_XFORM +#ifdef QT_MITSHM_CONVERSIONS + +static bool qt_mitshm_error = false; +static int qt_mitshm_errorhandler( Display*, XErrorEvent* ) +{ + qt_mitshm_error = true; + return 0; +} + +static XImage* qt_XShmCreateImage( Display* dpy, Visual* visual, unsigned int depth, + int format, int /*offset*/, char* /*data*/, unsigned int width, unsigned int height, + int /*bitmap_pad*/, int /*bytes_per_line*/, XShmSegmentInfo* shminfo ) +{ + if( width * height * depth < 100*100*32 ) + return NULL; + static int shm_inited = -1; + if( shm_inited == -1 ) { + if( XShmQueryExtension( dpy )) + shm_inited = 1; + else + shm_inited = 0; + } + if( shm_inited == 0 ) + return NULL; + XImage* xi = XShmCreateImage( dpy, visual, depth, format, NULL, shminfo, width, + height ); + if( xi == NULL ) + return NULL; + shminfo->shmid = shmget( IPC_PRIVATE, xi->bytes_per_line * xi->height, + IPC_CREAT|0600); + if( shminfo->shmid < 0 ) { + XDestroyImage( xi ); + return NULL; + } + shminfo->readOnly = False; + shminfo->shmaddr = (char*)shmat( shminfo->shmid, 0, 0 ); + if( shminfo->shmaddr == (char*)-1 ) { + XDestroyImage( xi ); + shmctl( shminfo->shmid, IPC_RMID, 0 ); + return NULL; + } + xi->data = shminfo->shmaddr; +#ifndef QT_MITSHM_RMID_IGNORES_REFCOUNT + // mark as deleted to automatically free the memory in case + // of a crash (but this doesn't work e.g. on Solaris) + shmctl( shminfo->shmid, IPC_RMID, 0 ); +#endif + if( shm_inited == 1 ) { // first time + XErrorHandler old_h = XSetErrorHandler( qt_mitshm_errorhandler ); + XShmAttach( dpy, shminfo ); + shm_inited = 2; + XSync( dpy, False ); + XSetErrorHandler( old_h ); + if( qt_mitshm_error ) { // oops ... perhaps we are remote? + shm_inited = 0; + XDestroyImage( xi ); + shmdt( shminfo->shmaddr ); +#ifdef QT_MITSHM_RMID_IGNORES_REFCOUNT + shmctl( shminfo->shmid, IPC_RMID, 0 ); +#endif + return NULL; + } + } else + XShmAttach( dpy, shminfo ); + return xi; +} + +static void qt_XShmDestroyImage( XImage* xi, XShmSegmentInfo* shminfo ) +{ + XShmDetach( QPaintDevice::x11AppDisplay(), shminfo ); + XDestroyImage( xi ); + shmdt( shminfo->shmaddr ); +#ifdef QT_MITSHM_RMID_IGNORES_REFCOUNT + shmctl( shminfo->shmid, IPC_RMID, 0 ); +#endif +} + +static XImage* qt_XShmGetImage( const QPixmap* pix, int format, + XShmSegmentInfo* shminfo ) +{ + XImage* xi = qt_XShmCreateImage( pix->x11Display(), (Visual*)pix->x11Visual(), + pix->depth(), format, 0, 0, pix->width(), pix->height(), 32, 0, shminfo ); + if( xi == NULL ) + return NULL; + if( XShmGetImage( pix->x11Display(), pix->handle(), xi, 0, 0, AllPlanes ) == False ) { + qt_XShmDestroyImage( xi, shminfo ); + return NULL; + } + return xi; +} + +#endif // QT_MITSHM_CONVERSIONS /***************************************************************************** Internal functions @@ -625,9 +728,20 @@ QImage QPixmap::convertToImage() const d = 32; // > 8 ==> 32 XImage *xi = (XImage *)data->ximage; // any cached ximage? - if ( !xi ) // fetch data from X server - xi = XGetImage( x11Display(), hd, 0, 0, w, h, AllPlanes, +#ifdef QT_MITSHM_CONVERSIONS + bool mitshm_ximage = false; + XShmSegmentInfo shminfo; +#endif + if ( !xi ) { // fetch data from X server +#ifdef QT_MITSHM_CONVERSIONS + xi = qt_XShmGetImage( this, mono ? XYPixmap : ZPixmap, &shminfo ); + if( xi ) { + mitshm_ximage = true; + } else +#endif + xi = XGetImage( x11Display(), hd, 0, 0, w, h, AllPlanes, mono ? XYPixmap : ZPixmap ); + } Q_CHECK_PTR( xi ); QImage::Endian bitOrder = QImage::IgnoreEndian; @@ -636,15 +750,31 @@ QImage QPixmap::convertToImage() const QImage::LittleEndian : QImage::BigEndian; } image.create( w, h, d, 0, bitOrder ); - if ( image.isNull() ) // could not create image + if ( image.isNull() ) { // could not create image +#ifdef QT_MITSHM_CONVERSIONS + if( mitshm_ximage ) + qt_XShmDestroyImage( xi, &shminfo ); + else +#endif + qSafeXDestroyImage( xi ); return image; + } const QPixmap* msk = mask(); const QPixmap *alf = data->alphapm; QImage alpha; if (alf) { - XImage *axi = XGetImage(x11Display(), alf->hd, 0, 0, w, h, AllPlanes, ZPixmap); + XImage* axi; +#ifdef QT_MITSHM_CONVERSIONS + bool mitshm_aximage = false; + XShmSegmentInfo ashminfo; + axi = qt_XShmGetImage( alf, ZPixmap, &ashminfo ); + if( axi ) { + mitshm_aximage = true; + } else +#endif + axi = XGetImage(x11Display(), alf->hd, 0, 0, w, h, AllPlanes, ZPixmap); if (axi) { image.setAlphaBuffer( TRUE ); @@ -658,7 +788,12 @@ QImage QPixmap::convertToImage() const src += axi->bytes_per_line; } - qSafeXDestroyImage( axi ); +#ifdef QT_MITSHM_CONVERSIONS + if( mitshm_aximage ) + qt_XShmDestroyImage( axi, &ashminfo ); + else +#endif + qSafeXDestroyImage( axi ); } } else if (msk) { image.setAlphaBuffer( TRUE ); @@ -800,6 +935,12 @@ QImage QPixmap::convertToImage() const xi->bits_per_pixel ); #endif image.reset(); +#ifdef QT_MITSHM_CONVERSIONS + if( mitshm_ximage ) + qt_XShmDestroyImage( xi, &shminfo ); + else +#endif + qSafeXDestroyImage( xi ); return image; } @@ -905,10 +1046,22 @@ QImage QPixmap::convertToImage() const delete [] carr; } if ( data->optim != BestOptim ) { // throw away image data - qSafeXDestroyImage( xi ); +#ifdef QT_MITSHM_CONVERSIONS + if( mitshm_ximage ) + qt_XShmDestroyImage( xi, &shminfo ); + else +#endif + qSafeXDestroyImage( xi ); ((QPixmap*)this)->data->ximage = 0; - } else // keep ximage data + } else { // keep ximage data +#ifdef QT_MITSHM_CONVERSIONS + if( mitshm_ximage ) { // copy the XImage? + qt_XShmDestroyImage( xi, &shminfo ); + xi = 0; + } +#endif ((QPixmap*)this)->data->ximage = xi; + } return image; } @@ -1078,6 +1231,11 @@ bool QPixmap::convertFromImage( const QI bool trucol = (visual->c_class == TrueColor); int nbytes = image.numBytes(); uchar *newbits= 0; + int newbits_size = 0; +#ifdef QT_MITSHM_CONVERSIONS + bool mitshm_ximage = false; + XShmSegmentInfo shminfo; +#endif if ( trucol ) { // truecolor display QRgb pix[256]; // pixel translation table @@ -1106,9 +1264,18 @@ bool QPixmap::convertFromImage( const QI } } - xi = XCreateImage( dpy, visual, dd, ZPixmap, 0, 0, w, h, 32, 0 ); +#ifdef QT_MITSHM_CONVERSIONS + xi = qt_XShmCreateImage( dpy, visual, dd, ZPixmap, 0, 0, w, h, 32, 0, &shminfo ); + if( xi != NULL ) { + mitshm_ximage = true; + newbits = (uchar*)xi->data; + } + else +#endif + xi = XCreateImage( dpy, visual, dd, ZPixmap, 0, 0, w, h, 32, 0 ); Q_CHECK_PTR( xi ); - newbits = (uchar *)malloc( xi->bytes_per_line*h ); + if( newbits == NULL ) + newbits = (uchar *)malloc( xi->bytes_per_line*h ); Q_CHECK_PTR( newbits ); if ( !newbits ) // no memory return FALSE; @@ -1314,6 +1481,7 @@ bool QPixmap::convertFromImage( const QI } newbits = (uchar *)malloc( nbytes ); // copy image into newbits + newbits_size = nbytes; Q_CHECK_PTR( newbits ); if ( !newbits ) // no memory return FALSE; @@ -1431,11 +1599,18 @@ bool QPixmap::convertFromImage( const QI } if ( !xi ) { // X image not created - xi = XCreateImage( dpy, visual, dd, ZPixmap, 0, 0, w, h, 32, 0 ); +#ifdef QT_MITSHM_CONVERSIONS + xi = qt_XShmCreateImage( dpy, visual, dd, ZPixmap, 0, 0, w, h, 32, 0, &shminfo ); + if( xi != NULL ) + mitshm_ximage = true; + else +#endif + xi = XCreateImage( dpy, visual, dd, ZPixmap, 0, 0, w, h, 32, 0 ); if ( xi->bits_per_pixel == 16 ) { // convert 8 bpp ==> 16 bpp ushort *p2; int p2inc = xi->bytes_per_line/sizeof(ushort); ushort *newerbits = (ushort *)malloc( xi->bytes_per_line * h ); + newbits_size = xi->bytes_per_line * h; Q_CHECK_PTR( newerbits ); if ( !newerbits ) // no memory return FALSE; @@ -1453,7 +1628,15 @@ bool QPixmap::convertFromImage( const QI "(bpp=%d)", xi->bits_per_pixel ); #endif } - xi->data = (char *)newbits; +#ifdef QT_MITSHM_CONVERSIONS + if( newbits_size > 0 && mitshm_ximage ) { // need to copy to shared memory + memcpy( xi->data, newbits, newbits_size ); + free( newbits ); + newbits = (uchar*)xi->data; + } + else +#endif + xi->data = (char *)newbits; } if ( hd && (width() != (int)w || height() != (int)h || this->depth() != dd) ) { @@ -1486,19 +1669,24 @@ bool QPixmap::convertFromImage( const QI } - XPutImage( dpy, hd, qt_xget_readonly_gc( x11Screen(), FALSE ), - xi, 0, 0, 0, 0, w, h ); +#ifdef QT_MITSHM_CONVERSIONS + if( mitshm_ximage ) + XShmPutImage( dpy, hd, qt_xget_readonly_gc( x11Screen(), FALSE ), + xi, 0, 0, 0, 0, w, h, False ); + else +#endif + XPutImage( dpy, hd, qt_xget_readonly_gc( x11Screen(), FALSE ), + xi, 0, 0, 0, 0, w, h ); - if ( data->optim != BestOptim ) { // throw away image - qSafeXDestroyImage( xi ); - data->ximage = 0; - } else { // keep ximage that we created - data->ximage = xi; - } data->w = w; data->h = h; data->d = dd; + XImage* axi = NULL; +#ifdef QT_MITSHM_CONVERSIONS + bool mitshm_aximage = false; + XShmSegmentInfo ashminfo; +#endif if ( image.hasAlphaBuffer() ) { QBitmap m; m = image.createAlphaMask( conversion_flags ); @@ -1534,13 +1722,22 @@ bool QPixmap::convertFromImage( const QI data->alphapm->rendhd = (HANDLE) XftDrawCreateAlpha( x11Display(), data->alphapm->hd, 8 ); - XImage *axi = XCreateImage(x11Display(), (Visual *) x11Visual(), - 8, ZPixmap, 0, 0, w, h, 8, 0); +#ifdef QT_MITSHM_CONVERSIONS + axi = qt_XShmCreateImage( x11Display(), (Visual*)x11Visual(), + 8, ZPixmap, 0, 0, w, h, 8, 0, &ashminfo ); + if( axi != NULL ) + mitshm_aximage = true; + else +#endif + axi = XCreateImage(x11Display(), (Visual *) x11Visual(), + 8, ZPixmap, 0, 0, w, h, 8, 0); if (axi) { - // the data is deleted by qSafeXDestroyImage - axi->data = (char *) malloc(h * axi->bytes_per_line); - Q_CHECK_PTR( axi->data ); + if( axi->data==NULL ) { + // the data is deleted by qSafeXDestroyImage + axi->data = (char *) malloc(h * axi->bytes_per_line); + Q_CHECK_PTR( axi->data ); + } char *aptr = axi->data; if (image.depth() == 32) { @@ -1558,14 +1755,48 @@ bool QPixmap::convertFromImage( const QI } GC gc = XCreateGC(x11Display(), data->alphapm->hd, 0, 0); - XPutImage(dpy, data->alphapm->hd, gc, axi, 0, 0, 0, 0, w, h); +#ifdef QT_MITSHM_CONVERSIONS + if( mitshm_aximage ) + XShmPutImage( dpy, data->alphapm->hd, gc, axi, 0, 0, 0, 0, w, h, False ); + else +#endif + XPutImage(dpy, data->alphapm->hd, gc, axi, 0, 0, 0, 0, w, h); XFreeGC(x11Display(), gc); - qSafeXDestroyImage(axi); } } #endif // QT_NO_XFTFREETYPE } +#ifdef QT_MITSHM_CONVERSIONS + if( mitshm_ximage || mitshm_aximage ) + XSync( x11Display(), False ); // wait until processed +#endif + + if ( data->optim != BestOptim ) { // throw away image +#ifdef QT_MITSHM_CONVERSIONS + if( mitshm_ximage ) + qt_XShmDestroyImage( xi, &shminfo ); + else +#endif + qSafeXDestroyImage( xi ); + data->ximage = 0; + } else { // keep ximage that we created +#ifdef QT_MITSHM_CONVERSIONS + if( mitshm_ximage ) { // copy the XImage? + qt_XShmDestroyImage( xi, &shminfo ); + xi = 0; + } +#endif + data->ximage = xi; + } + if( axi ) { +#ifdef QT_MITSHM_CONVERSIONS + if( mitshm_aximage ) + qt_XShmDestroyImage( axi, &ashminfo ); + else +#endif + qSafeXDestroyImage(axi); + } return TRUE; } @@ -1722,7 +1953,7 @@ QPixmap QPixmap::xForm( const QWMatrix & return pm; } -#if defined(QT_MITSHM) +#if defined(QT_MITSHM_XFORM) static bool try_once = TRUE; if (try_once) { try_once = FALSE; @@ -1755,7 +1986,7 @@ QPixmap QPixmap::xForm( const QWMatrix & dbpl = ((w*bpp+31)/32)*4; dbytes = dbpl*h; -#if defined(QT_MITSHM) +#if defined(QT_MITSHM_XFORM) if ( use_mitshm ) { dptr = (uchar *)xshmimg->data; uchar fillbyte = bpp == 8 ? white.pixel() : 0xff; @@ -1771,7 +2002,7 @@ QPixmap QPixmap::xForm( const QWMatrix & memset( dptr, Qt::white.pixel( x11Screen() ), dbytes ); else memset( dptr, 0xff, dbytes ); -#if defined(QT_MITSHM) +#if defined(QT_MITSHM_XFORM) } #endif @@ -1802,7 +2033,7 @@ QPixmap QPixmap::xForm( const QWMatrix & } else { xbpl = (w*bpp)/8; p_inc = dbpl - xbpl; -#if defined(QT_MITSHM) +#if defined(QT_MITSHM_XFORM) if ( use_mitshm ) p_inc = xshmimg->bytes_per_line - xbpl; #endif @@ -1839,7 +2070,7 @@ QPixmap QPixmap::xForm( const QWMatrix & QPixmap pm( w, h ); pm.data->uninit = FALSE; pm.x11SetScreen( x11Screen() ); -#if defined(QT_MITSHM) +#if defined(QT_MITSHM_XFORM) if ( use_mitshm ) { XCopyArea( dpy, xshmpm, pm.handle(), gc, 0, 0, w, h, 0, 0 ); } else { @@ -1848,7 +2079,7 @@ QPixmap QPixmap::xForm( const QWMatrix & ZPixmap, 0, (char *)dptr, w, h, 32, 0 ); XPutImage( dpy, pm.handle(), gc, xi, 0, 0, 0, 0, w, h); qSafeXDestroyImage( xi ); -#if defined(QT_MITSHM) +#if defined(QT_MITSHM_XFORM) } #endif --- qt.orig/mkspecs/linux-g++/qplatformdefs.h +++ qt.patched/mkspecs/linux-g++/qplatformdefs.h @@ -102,5 +102,6 @@ #define QT_VSNPRINTF ::vsnprintf #endif +#define QT_MITSHM #endif // QPLATFORMDEFS_H --- qt.orig/mkspecs/linux-g++/qplatformdefs.h +++ qt.patched/mkspecs/linux-g++/qplatformdefs.h @@ -102,5 +102,6 @@ #define QT_VSNPRINTF ::vsnprintf #endif +#define QT_MITSHM #endif // QPLATFORMDEFS_H