diff options
author | Robert Xu <[email protected]> | 2011-11-12 18:13:39 -0500 |
---|---|---|
committer | Robert Xu <[email protected]> | 2011-11-12 18:13:39 -0500 |
commit | cd1f97695be1245ab19058d4fbc34e5697cc5383 (patch) | |
tree | b265d96856632dc78e566d337f7eff254b6695f7 /opensuse/core/qt3/0005-qpixmap_mitshm.patch | |
parent | 21fcfa3348213aa87f0e3aef62ca4720c6d31cb7 (diff) | |
download | tde-packaging-cd1f97695be1245ab19058d4fbc34e5697cc5383.tar.gz tde-packaging-cd1f97695be1245ab19058d4fbc34e5697cc5383.zip |
fix up tdebase and add qt3
Diffstat (limited to 'opensuse/core/qt3/0005-qpixmap_mitshm.patch')
-rw-r--r-- | opensuse/core/qt3/0005-qpixmap_mitshm.patch | 569 |
1 files changed, 569 insertions, 0 deletions
diff --git a/opensuse/core/qt3/0005-qpixmap_mitshm.patch b/opensuse/core/qt3/0005-qpixmap_mitshm.patch new file mode 100644 index 000000000..e6683f726 --- /dev/null +++ b/opensuse/core/qt3/0005-qpixmap_mitshm.patch @@ -0,0 +1,569 @@ +qt-bugs@ issue : 11790 (part of) +applied: no +author: Lubos Lunak <[email protected]> + +NOTE: Needs #define QT_MITSHM in the matching qplatformdefs.h file. This + patch does so only for linux-g++ and linux-g++-distcc platforms. + +MITSHM extension support for QPixmap<->QImage conversions. + +Hello, + + the review and apply the attached patches that improve performance of +QImage->QPixmap conversions. They should be applied in order +'mitshm','more_local' and 'fast', but they're independent from each other +(well, besides merging problems). + + Mitshm patch adds MITSHM extension support for both +QPixmap::convertFromImage() and QPixmap::convertToImage(). I've noticed there +was some MITSHM support already, turned off by default, but it was used only +for QPixmap::xForm() , and it used shared pixmaps (and I'd bet nobody uses +it). My patch adds shared ximages support for faster pixmap<->image +conversions. Since I don't understand the xForm() code much, and I didn't +want to do anything with it, I added three #define's: + - QT_MITSHM generally enabling MITSHM support, which should be set in +qplatformsdefs.h (or wherever you setup platform specific stuff), it can be +enabled at least on Linux + - QT_MITSHM_CONVERSIONS - this is for my new code + - QT_MITSHM_XFORM - this is for the xForm() code + There's one more #define, QT_MITSHM_RMID_IGNORES_REFCOUNT. Glibc +documentation of shmctl( ... IPC_RMID ) quite clearly says that the memory +segment is freed only after the refcount increased by shmat() and decreased +by shmdt() is 0. However, at least according to +http://bugs.kde.org/show_bug.cgi?id=27517 , this doesn't happen on other +platforms for some strange reason. Such platforms should have this #define if +you ever consider supporting MITSHM on them. + + The lower limit for using MITSHM for the image is about 8KiB +(width*height*depth > 100*100*32 ). Also, BestOptim in such case doesn't keep +the ximage, as the shared ximage is always freed before the function returns +(I don't know if it's worth copying it). + + The second patch ('more_local'), in short, does nothing. Besides improving +performance by about 10% by making variables more "local", making few of them +const, and also making some of them unsigned (this help gcc for some reason). + + The last one, 'fast', moves some if's out of the loops, and handles some most +common case specially (15bpp, 16bpp and 32bpp ximage depths). 32bpp case, if +the endianess matches, is simply uses memcpy(), for the 15/16bpp depth, +variables are replaced directly by matching values, statements are a bit +reordered and merged when suitable, and again, in case endianess matches, +pixels are written simply as Q_INT16. Most probably it would also help to +process two pixels at once and write them as Q_INT32, but I didn't want to +complicate the code too much (later >;) ). + + The last snippet of 'fast' handles case when xi->bytes_per_line is not equal +to width for 8bpp ximage. I'm not actually sure if that can ever happen, but +since I've already written it *shrug*. + + The 'more_local' and 'fast' patches change only convertFromImage(), as I +don't think convertToImage() is that performance critical (but it's as +unoptimized as convertFromImage() was). + + Maybe some numbers. The difference is of course mainly visible with larger +pixmaps. The two optimizations alone reduce the time to 50% for 32bpp, to 70% +for 16bpp. The MITSHM support, when other patches are already applied too, +for 32bpp images saves about 33%. Together, the total time is reduced to +about 40% for 32bpp. Imlib probably still beats that, but at least this +obsoletes KPixmapIO. + + +--- src/kernel/qpixmap_x11.cpp ++++ 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 +@@ -627,9 +730,20 @@ QImage QPixmap::convertToImage() const + d = 32; // > 8 ==> 32 + + XImage *xi = (XImage *)data->ximage; // any cached ximage? +- if ( !xi ) // fetch data from X server ++#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 ); + if (!xi) + return image; // null image +@@ -640,15 +754,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 ); +@@ -662,6 +792,11 @@ QImage QPixmap::convertToImage() const + src += axi->bytes_per_line; + } + ++#ifdef QT_MITSHM_CONVERSIONS ++ if( mitshm_aximage ) ++ qt_XShmDestroyImage( axi, &ashminfo ); ++ else ++#endif + qSafeXDestroyImage( axi ); + } + } else if (msk) { +@@ -804,6 +939,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; + } + +@@ -909,10 +1050,22 @@ QImage QPixmap::convertToImage() const + delete [] carr; + } + if ( data->optim != BestOptim ) { // throw away image data ++#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; + } +@@ -1085,6 +1238,11 @@ bool QPixmap::convertFromImage( const QI + bool trucol = (visual->c_class == TrueColor || visual->c_class == DirectColor); + 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 +@@ -1113,10 +1271,18 @@ bool QPixmap::convertFromImage( const QI + } + } + ++#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 ); + if (!xi) + return false; ++ if( newbits == NULL ) + newbits = (uchar *)malloc( xi->bytes_per_line*h ); + Q_CHECK_PTR( newbits ); + if ( !newbits ) // no memory +@@ -1323,6 +1489,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; +@@ -1440,11 +1607,18 @@ bool QPixmap::convertFromImage( const QI + } + + if ( !xi ) { // X image not created ++#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; +@@ -1462,6 +1636,14 @@ bool QPixmap::convertFromImage( const QI + "(bpp=%d)", xi->bits_per_pixel ); + #endif + } ++#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; + } + +@@ -1495,19 +1677,24 @@ bool QPixmap::convertFromImage( const QI + + } + ++#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 ); +@@ -1543,13 +1730,22 @@ bool QPixmap::convertFromImage( const QI + data->alphapm->rendhd = + (HANDLE) XftDrawCreateAlpha( x11Display(), data->alphapm->hd, 8 ); + +- XImage *axi = XCreateImage(x11Display(), (Visual *) x11Visual(), ++#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) { ++ 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) { +@@ -1567,14 +1763,48 @@ bool QPixmap::convertFromImage( const QI + } + + GC gc = XCreateGC(x11Display(), data->alphapm->hd, 0, 0); ++ #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; + } + +@@ -1737,7 +1967,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; +@@ -1770,7 +2000,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; +@@ -1786,7 +2016,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 + +@@ -1817,7 +2047,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 +@@ -1854,7 +2084,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 { +@@ -1863,7 +2093,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 + +--- mkspecs/linux-g++/qplatformdefs.h ++++ mkspecs/linux-g++/qplatformdefs.h +@@ -102,5 +102,6 @@ + #define QT_VSNPRINTF ::vsnprintf + #endif + ++#define QT_MITSHM + + #endif // QPLATFORMDEFS_H |