|
|
|
qt-bugs@ issue : 11790 (part of)
|
|
|
|
applied: no
|
|
|
|
author: Lubos Lunak <l.lunak@kde.org>
|
|
|
|
|
|
|
|
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.
|
|
|
|
|
|
|
|
|
|
|
|
--- work/qt-x11-free-3.3.8/src/kernel/qpixmap_x11.cpp
|
|
|
|
+++ work/qt-x11-free-3.3.8/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 );
|
|
|
|
+ }
|
|
|
|
TQ_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 );
|
|
|
|
- TQ_CHECK_PTR( xi );
|
|
|
|
if (!xi)
|
|
|
|
return false;
|
|
|
|
+ if( newbits == NULL )
|
|
|
|
newbits = (uchar *)malloc( xi->bytes_per_line*h );
|
|
|
|
TQ_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;
|
|
|
|
TQ_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;
|
|
|
|
TQ_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);
|
|
|
|
TQ_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
|
|
|
|
|
|
|
|
--- work/qt-x11-free-3.3.8/mkspecs/linux-g++/qplatformdefs.h
|
|
|
|
+++ work/qt-x11-free-3.3.8/mkspecs/linux-g++/qplatformdefs.h
|
|
|
|
@@ -102,5 +102,6 @@
|
|
|
|
#define QT_VSNPRINTF ::vsnprintf
|
|
|
|
#endif
|
|
|
|
|
|
|
|
+#define QT_MITSHM
|
|
|
|
|
|
|
|
#endif // QPLATFORMDEFS_H
|