diff options
author | Lorn Potter <lorn.potter@nokia.com> | 2010-11-09 01:23:37 (GMT) |
---|---|---|
committer | Lorn Potter <lorn.potter@nokia.com> | 2010-11-09 01:23:37 (GMT) |
commit | 6b8a95b2521d843ec2b3f7c787c15b92e4ea686f (patch) | |
tree | 346bc8925d83b2729f485d1259729fca931de07d /src/plugins | |
parent | bb8f085611f4cb91b7bde7220d407948edcc572c (diff) | |
parent | e00af84cc9230df411981d2f3b9296b61d5d1c50 (diff) | |
download | Qt-6b8a95b2521d843ec2b3f7c787c15b92e4ea686f.zip Qt-6b8a95b2521d843ec2b3f7c787c15b92e4ea686f.tar.gz Qt-6b8a95b2521d843ec2b3f7c787c15b92e4ea686f.tar.bz2 |
Merge branch '4.7' of scm.dev.nokia.troll.no:qt/oslo-staging-1 into 4.7
Diffstat (limited to 'src/plugins')
29 files changed, 1102 insertions, 383 deletions
diff --git a/src/plugins/accessible/widgets/simplewidgets.cpp b/src/plugins/accessible/widgets/simplewidgets.cpp index f39d538..4a3acbb 100644 --- a/src/plugins/accessible/widgets/simplewidgets.cpp +++ b/src/plugins/accessible/widgets/simplewidgets.cpp @@ -602,7 +602,7 @@ int QAccessibleDisplay::navigate(RelationFlag rel, int entry, QAccessibleInterfa return QAccessibleWidgetEx::navigate(rel, entry, target); } -/*! \reimp */ +/*! \internal */ QString QAccessibleDisplay::imageDescription() { #ifndef QT_NO_TOOLTIP @@ -612,7 +612,7 @@ QString QAccessibleDisplay::imageDescription() #endif } -/*! \reimp */ +/*! \internal */ QSize QAccessibleDisplay::imageSize() { QLabel *label = qobject_cast<QLabel *>(widget()); @@ -624,7 +624,7 @@ QSize QAccessibleDisplay::imageSize() return pixmap->size(); } -/*! \reimp */ +/*! \internal */ QRect QAccessibleDisplay::imagePosition(QAccessible2::CoordinateType coordType) { QLabel *label = qobject_cast<QLabel *>(widget()); diff --git a/src/plugins/bearer/connman/qconnmanengine.cpp b/src/plugins/bearer/connman/qconnmanengine.cpp index a8b8911..184ceb4 100644 --- a/src/plugins/bearer/connman/qconnmanengine.cpp +++ b/src/plugins/bearer/connman/qconnmanengine.cpp @@ -170,13 +170,26 @@ bool QConnmanEngine::hasIdentifier(const QString &id) void QConnmanEngine::connectToId(const QString &id) { QMutexLocker locker(&mutex); - QConnmanConnectThread *thread; - thread = new QConnmanConnectThread(this); - thread->setServicePath(serviceFromId(id)); - thread->setIdentifier(id); - connect(thread,SIGNAL(connectionError(QString,QBearerEngineImpl::ConnectionError)), - this,SIGNAL(connectionError(QString,QBearerEngineImpl::ConnectionError))); - thread->start(); + QString servicePath = serviceFromId(id); + QConnmanServiceInterface serv(servicePath); + if(!serv.isValid()) { + emit connectionError(id, QBearerEngineImpl::InterfaceLookupError); + } else { + if(serv.getType() != "cellular") { + + serv.connect(); + } else { + QOfonoManagerInterface ofonoManager(0); + QString modemPath = ofonoManager.currentModem().path(); + QOfonoDataConnectionManagerInterface dc(modemPath,0); + foreach(const QDBusObjectPath dcPath,dc.getPrimaryContexts()) { + if(dcPath.path().contains(servicePath.section("_",-1))) { + QOfonoPrimaryDataContextInterface primaryContext(dcPath.path(),0); + primaryContext.setActive(true); + } + } + } + } } void QConnmanEngine::disconnectFromId(const QString &id) @@ -791,62 +804,6 @@ bool QConnmanEngine::requiresPolling() const return false; } - -QConnmanConnectThread::QConnmanConnectThread(QObject *parent) - :QThread(parent), - servicePath(), identifier() -{ -} - -QConnmanConnectThread::~QConnmanConnectThread() -{ -} - -void QConnmanConnectThread::stop() -{ - if(currentThread() != this) { - QMetaObject::invokeMethod(this, "quit", - Qt::QueuedConnection); - } else { - quit(); - } - wait(); -} - -void QConnmanConnectThread::run() -{ - QConnmanServiceInterface serv(servicePath); - if(!serv.isValid()) { - emit connectionError(identifier, QBearerEngineImpl::InterfaceLookupError); - } else { - if(serv.getType() != "cellular") { - serv.connect(); - } else { - QOfonoManagerInterface ofonoManager(0); - QString modemPath = ofonoManager.currentModem().path(); - QOfonoDataConnectionManagerInterface dc(modemPath,0); - foreach(const QDBusObjectPath dcPath,dc.getPrimaryContexts()) { - if(dcPath.path().contains(servicePath.section("_",-1))) { - QOfonoPrimaryDataContextInterface primaryContext(dcPath.path(),0); - primaryContext.setActive(true); - } - } - } - } -} - -void QConnmanConnectThread::setServicePath(const QString &path) -{ - QMutexLocker locker(&mutex); - servicePath = path; -} - -void QConnmanConnectThread::setIdentifier(const QString &id) -{ - QMutexLocker locker(&mutex); - identifier = id; -} - QT_END_NAMESPACE #endif // QT_NO_DBUS diff --git a/src/plugins/bearer/connman/qconnmanengine.h b/src/plugins/bearer/connman/qconnmanengine.h index 569bbc7..2a2308f 100644 --- a/src/plugins/bearer/connman/qconnmanengine.h +++ b/src/plugins/bearer/connman/qconnmanengine.h @@ -59,14 +59,12 @@ #include <QMap> #include <QVariant> -#include <QtCore/qthread.h> #ifndef QT_NO_BEARERMANAGEMENT #ifndef QT_NO_DBUS QT_BEGIN_NAMESPACE -class QConnmanConnectThread; class QConnmanEngine : public QBearerEngineImpl { Q_OBJECT @@ -141,33 +139,8 @@ private: bool isRoamingAllowed(const QString &context); protected: bool requiresPolling() const; - QConnmanConnectThread *connThread; }; -class QConnmanConnectThread : public QThread -{ - Q_OBJECT - -public: - QConnmanConnectThread(QObject *parent = 0); - ~QConnmanConnectThread(); - bool keepRunning; - void stop(); - void setServicePath(const QString &path); - void setIdentifier(const QString &id); - -Q_SIGNALS: - void connectionError(const QString &id, QBearerEngineImpl::ConnectionError error); - -protected: - void run(); - QString servicePath; - QString identifier; - -private: - QMutex mutex; - -}; QT_END_NAMESPACE diff --git a/src/plugins/bearer/connman/qconnmanservice_linux.cpp b/src/plugins/bearer/connman/qconnmanservice_linux.cpp index 549a07a..952a444 100644 --- a/src/plugins/bearer/connman/qconnmanservice_linux.cpp +++ b/src/plugins/bearer/connman/qconnmanservice_linux.cpp @@ -106,7 +106,7 @@ if (QLatin1String(signal) == SIGNAL(propertyChanged(QString,QDBusVariant))) { QObject::connect(helper,SIGNAL(propertyChangedContext(const QString &,const QString &,const QDBusVariant &)), - this,SIGNAL(propertyChangedContext(const QString &,const QString &,const QDBusVariant &))); + this,SIGNAL(propertyChangedContext(const QString &,const QString &,const QDBusVariant &)), Qt::UniqueConnection); } } @@ -338,7 +338,7 @@ void QConnmanNetworkInterface::connectNotify(const char *signal) this->path(), QLatin1String(CONNMAN_NETWORK_INTERFACE), QLatin1String("PropertyChanged"), - this,SIGNAL(propertyChanged(QString,QDBusVariant))) ) { + this,SIGNAL(propertyChanged(QString,QDBusVariant)))) { qWarning() << "network properties not connected"; } } @@ -353,7 +353,7 @@ void QConnmanNetworkInterface::connectNotify(const char *signal) helper,SLOT(propertyChanged(QString,QDBusVariant))); QObject::connect(helper,SIGNAL(propertyChangedContext(const QString &,const QString &,const QDBusVariant &)), - this,SIGNAL(propertyChangedContext(const QString &,const QString &,const QDBusVariant &))); + this,SIGNAL(propertyChangedContext(const QString &,const QString &,const QDBusVariant &)), Qt::UniqueConnection); } } @@ -538,7 +538,7 @@ void QConnmanServiceInterface::connectNotify(const char *signal) helper,SLOT(propertyChanged(QString,QDBusVariant))); QObject::connect(helper,SIGNAL(propertyChangedContext(const QString &,const QString &,const QDBusVariant &)), - this,SIGNAL(propertyChangedContext(const QString &,const QString &,const QDBusVariant &))); + this,SIGNAL(propertyChangedContext(const QString &,const QString &,const QDBusVariant &)), Qt::UniqueConnection); } } @@ -569,10 +569,9 @@ QVariant QConnmanServiceInterface::getProperty(const QString &property) return var; } -// clearProperty void QConnmanServiceInterface::connect() { - QDBusReply<QVariantMap> reply = this->call(QLatin1String("Connect")); + this->asyncCall(QLatin1String("Connect")); } void QConnmanServiceInterface::disconnect() @@ -866,7 +865,7 @@ void QConnmanTechnologyInterface::connectNotify(const char *signal) helper,SLOT(propertyChanged(QString,QDBusVariant))); QObject::connect(helper,SIGNAL(propertyChangedContext(const QString &,const QString &,const QDBusVariant &)), - this,SIGNAL(propertyChangedContext(const QString &,const QString &,const QDBusVariant &))); + this,SIGNAL(propertyChangedContext(const QString &,const QString &,const QDBusVariant &)), Qt::UniqueConnection); } } @@ -1031,7 +1030,7 @@ void QConnmanDeviceInterface::connectNotify(const char *signal) helper,SLOT(propertyChanged(QString,QDBusVariant))); QObject::connect(helper,SIGNAL(propertyChangedContext(const QString &,const QString &,const QDBusVariant &)), - this,SIGNAL(propertyChangedContext(const QString &,const QString &,const QDBusVariant &))); + this,SIGNAL(propertyChangedContext(const QString &,const QString &,const QDBusVariant &)), Qt::UniqueConnection); } } diff --git a/src/plugins/bearer/connman/qofonoservice_linux.cpp b/src/plugins/bearer/connman/qofonoservice_linux.cpp index 955f4b1..52f596b 100644 --- a/src/plugins/bearer/connman/qofonoservice_linux.cpp +++ b/src/plugins/bearer/connman/qofonoservice_linux.cpp @@ -262,7 +262,7 @@ void QOfonoModemInterface::connectNotify(const char *signal) QObject::connect(helper,SIGNAL(propertyChangedContext(const QString &,const QString &,const QDBusVariant &)), - this,SIGNAL(propertyChangedContext(const QString &,const QString &,const QDBusVariant &))); + this,SIGNAL(propertyChangedContext(const QString &,const QString &,const QDBusVariant &)), Qt::UniqueConnection); }} void QOfonoModemInterface::disconnectNotify(const char *signal) @@ -385,7 +385,7 @@ if (QLatin1String(signal) == SIGNAL(propertyChanged(QString,QDBusVariant))) { QObject::connect(helper,SIGNAL(propertyChangedContext(const QString &,const QString &,const QDBusVariant &)), - this,SIGNAL(propertyChangedContext(const QString &,const QString &,const QDBusVariant &))); + this,SIGNAL(propertyChangedContext(const QString &,const QString &,const QDBusVariant &)), Qt::UniqueConnection); } } @@ -483,7 +483,7 @@ if (QLatin1String(signal) == SIGNAL(propertyChanged(QString,QDBusVariant))) { QObject::connect(helper,SIGNAL(propertyChangedContext(const QString &,const QString &,const QDBusVariant &)), - this,SIGNAL(propertyChangedContext(const QString &,const QString &,const QDBusVariant &))); + this,SIGNAL(propertyChangedContext(const QString &,const QString &,const QDBusVariant &)), Qt::UniqueConnection); } } @@ -586,7 +586,7 @@ if (QLatin1String(signal) == SIGNAL(propertyChanged(QString,QDBusVariant))) { QObject::connect(helper,SIGNAL(propertyChangedContext(const QString &,const QString &,const QDBusVariant &)), - this,SIGNAL(propertyChangedContext(const QString &,const QString &,const QDBusVariant &))); + this,SIGNAL(propertyChangedContext(const QString &,const QString &,const QDBusVariant &)), Qt::UniqueConnection); } } @@ -675,7 +675,7 @@ if (QLatin1String(signal) == SIGNAL(propertyChanged(QString,QDBusVariant))) { QObject::connect(helper,SIGNAL(propertyChangedContext(const QString &,const QString &,const QDBusVariant &)), - this,SIGNAL(propertyChangedContext(const QString &,const QString &,const QDBusVariant &))); + this,SIGNAL(propertyChangedContext(const QString &,const QString &,const QDBusVariant &)), Qt::UniqueConnection); } } @@ -794,7 +794,7 @@ if (QLatin1String(signal) == SIGNAL(propertyChanged(QString,QDBusVariant))) { QObject::connect(helper,SIGNAL(propertyChangedContext(const QString &,const QString &,const QDBusVariant &)), - this,SIGNAL(propertyChangedContext(const QString &,const QString &,const QDBusVariant &))); + this,SIGNAL(propertyChangedContext(const QString &,const QString &,const QDBusVariant &)), Qt::UniqueConnection); } } diff --git a/src/plugins/bearer/icd/maemo_icd.cpp b/src/plugins/bearer/icd/maemo_icd.cpp index 4f879e3..57ab0a8 100644 --- a/src/plugins/bearer/icd/maemo_icd.cpp +++ b/src/plugins/bearer/icd/maemo_icd.cpp @@ -508,6 +508,7 @@ uint IcdPrivate::state(QList<IcdStateResult>& state_results) mInterface.clear(); while ((time(0)<=(started+timeout_secs)) && mInterface.isEmpty()) { mDBus->synchronousDispatch(1000); + QCoreApplication::sendPostedEvents(icd, QEvent::MetaCall); } if (time(0)>(started+timeout_secs)) { @@ -685,6 +686,7 @@ uint IcdPrivate::addrinfo(QList<IcdAddressInfoResult>& addr_results) mInterface.clear(); while ((time(0)<=(started+timeout_secs)) && mInterface.isEmpty()) { mDBus->synchronousDispatch(1000); + QCoreApplication::sendPostedEvents(icd, QEvent::MetaCall); } if (time(0)>(started+timeout_secs)) { diff --git a/src/plugins/bearer/icd/qnetworksession_impl.cpp b/src/plugins/bearer/icd/qnetworksession_impl.cpp index 37434e3..8d0f587 100644 --- a/src/plugins/bearer/icd/qnetworksession_impl.cpp +++ b/src/plugins/bearer/icd/qnetworksession_impl.cpp @@ -679,7 +679,7 @@ void QNetworkSessionPrivateImpl::open() if (serviceConfig.isValid()) { lastError = QNetworkSession::OperationNotSupportedError; emit QNetworkSessionPrivate::error(lastError); - } else if (!isOpen) { + } else if (!opened) { if (publicConfig.type() == QNetworkConfiguration::UserChoice) { /* Caller is trying to connect to default IAP. * At this time we will not know the IAP details so we just diff --git a/src/plugins/bearer/symbian/qnetworksession_impl.cpp b/src/plugins/bearer/symbian/qnetworksession_impl.cpp index 7f81397..85723ce 100644 --- a/src/plugins/bearer/symbian/qnetworksession_impl.cpp +++ b/src/plugins/bearer/symbian/qnetworksession_impl.cpp @@ -760,7 +760,7 @@ void QNetworkSessionPrivateImpl::Error(TInt /*aError*/) { #ifdef QT_BEARERMGMT_SYMBIAN_DEBUG qDebug() << "QNS this : " << QString::number((uint)this) << " - " - << "roaming Error() occured, isOpen is: " << isOpen; + << "roaming Error() occurred, isOpen is: " << isOpen; #endif if (isOpen) { isOpen = false; diff --git a/src/plugins/bearer/symbian/symbian.pri b/src/plugins/bearer/symbian/symbian.pri index e874945..8d92f57 100644 --- a/src/plugins/bearer/symbian/symbian.pri +++ b/src/plugins/bearer/symbian/symbian.pri @@ -1,7 +1,7 @@ TARGET = qsymbianbearer include(../../qpluginbase.pri) -QT += network +QT = core network HEADERS += ../symbianengine.h \ ../qnetworksession_impl.h diff --git a/src/plugins/bearer/symbian/symbianengine.cpp b/src/plugins/bearer/symbian/symbianengine.cpp index ef273c1..b4dfc4d 100644 --- a/src/plugins/bearer/symbian/symbianengine.cpp +++ b/src/plugins/bearer/symbian/symbianengine.cpp @@ -976,7 +976,7 @@ void SymbianEngine::RunL() QMutexLocker locker(&mutex); if (iStatus != KErrCancel) { - // By default, start relistening notifications. Stop only if interesting event occured. + // By default, start relistening notifications. Stop only if interesting event occurred. iWaitingCommsDatabaseNotifications = true; RDbNotifier::TEvent event = STATIC_CAST(RDbNotifier::TEvent, iStatus.Int()); switch (event) { diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp index 4869eba..c16a242 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp @@ -55,6 +55,7 @@ #include <private/qpixmap_raster_p.h> #include <private/qimagepixmapcleanuphooks_p.h> + QT_BEGIN_NAMESPACE class SurfaceCache; @@ -112,7 +113,11 @@ public: static inline int cacheCost(const QImage &img) { return img.width() * img.height() * img.depth() / 8; } #endif - void prepareForBlit(bool alpha); + enum BlitFlag { + HasAlpha = 0x1, + Premultiplied = 0x2 + }; + void prepareForBlit(uint blitFlags); IDirectFBSurface *surface; @@ -616,7 +621,12 @@ void QDirectFBPaintEngine::drawImage(const QRectF &r, const QImage &image, #if !defined QT_NO_DIRECTFB_PREALLOCATED || defined QT_DIRECTFB_IMAGECACHE bool release; IDirectFBSurface *imgSurface = d->getSurface(image, &release); - d->prepareForBlit(QDirectFBScreen::hasAlphaChannel(imgSurface)); + uint blitFlags = 0; + if (image.hasAlphaChannel()) + blitFlags |= QDirectFBPaintEnginePrivate::HasAlpha; + if (QDirectFBScreen::isPremultiplied(image.format())) + blitFlags |= QDirectFBPaintEnginePrivate::Premultiplied; + d->prepareForBlit(blitFlags); CLIPPED_PAINT(d->blit(r, imgSurface, sr)); if (release) { #if (Q_DIRECTFB_VERSION >= 0x010000) @@ -655,8 +665,14 @@ void QDirectFBPaintEngine::drawPixmap(const QRectF &r, const QPixmap &pixmap, QRasterPaintEngine::drawImage(r, *img, sr); } else { QDirectFBPaintEnginePrivate::unlock(dfbData); - d->prepareForBlit(pixmap.hasAlphaChannel()); IDirectFBSurface *s = dfbData->directFBSurface(); + uint blitFlags = 0; + if (pixmap.hasAlphaChannel()) + blitFlags |= QDirectFBPaintEnginePrivate::HasAlpha; + if (QDirectFBScreen::isPremultiplied(dfbData->pixelFormat())) + blitFlags |= QDirectFBPaintEnginePrivate::Premultiplied; + + d->prepareForBlit(blitFlags); CLIPPED_PAINT(d->blit(r, s, sr)); } } @@ -978,7 +994,7 @@ void QDirectFBPaintEnginePrivate::setCompositionMode(QPainter::CompositionMode m break; case QPainter::CompositionMode_SourceOver: compositionModeStatus &= ~PorterDuff_AlwaysBlend; - surface->SetPorterDuff(surface, DSPD_NONE); + surface->SetPorterDuff(surface, DSPD_SRC_OVER); break; case QPainter::CompositionMode_DestinationOver: surface->SetPorterDuff(surface, DSPD_DST_OVER); @@ -1031,13 +1047,18 @@ void QDirectFBPaintEnginePrivate::setRenderHints(QPainter::RenderHints hints) } } -void QDirectFBPaintEnginePrivate::prepareForBlit(bool alpha) +void QDirectFBPaintEnginePrivate::prepareForBlit(uint flags) { - DFBSurfaceBlittingFlags blittingFlags = alpha ? DSBLIT_BLEND_ALPHACHANNEL : DSBLIT_NOFX; + DFBSurfaceBlittingFlags blittingFlags = DSBLIT_NOFX; + if (flags & Premultiplied) + blittingFlags |= DSBLIT_SRC_PREMULTIPLY; + if (flags & HasAlpha) + blittingFlags |= DSBLIT_BLEND_ALPHACHANNEL; if (opacity != 255) { blittingFlags |= DSBLIT_BLEND_COLORALPHA; + surface->SetColor(surface, 0xff, 0xff, 0xff, opacity); } - surface->SetColor(surface, 0xff, 0xff, 0xff, opacity); + surface->SetBlittingFlags(surface, blittingFlags); } @@ -1154,13 +1175,18 @@ void QDirectFBPaintEnginePrivate::drawTiledPixmap(const QRectF &dest, const QPix QPointF offset = off; Q_ASSERT(transform.type() <= QTransform::TxScale); - prepareForBlit(pixmap.hasAlphaChannel()); QPixmapData *data = pixmap.pixmapData(); Q_ASSERT(data->classId() == QPixmapData::DirectFBClass); QDirectFBPixmapData *dfbData = static_cast<QDirectFBPixmapData*>(data); + IDirectFBSurface *sourceSurface = dfbData->directFBSurface(); + uint blitFlags = 0; + if (dfbData->hasAlphaChannel()) + blitFlags |= HasAlpha; + if (QDirectFBScreen::isPremultiplied(dfbData->pixelFormat())) + blitFlags |= Premultiplied; + prepareForBlit(blitFlags); QDirectFBPaintEnginePrivate::unlock(dfbData); const QSize pixmapSize = dfbData->size(); - IDirectFBSurface *sourceSurface = dfbData->directFBSurface(); if (transform.isScaling()) { Q_ASSERT(supportsStretchBlit()); Q_ASSERT(qMin(transform.m11(), transform.m22()) >= 0); diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp index c0d96d7..ce3a05a 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp @@ -251,12 +251,6 @@ bool QDirectFBPixmapData::fromDataBufferDescription(const DFBDataBufferDescripti } QDirectFBPointer<IDirectFBImageProvider> provider(providerPtr); - DFBSurfaceDescription surfaceDescription; - if ((result = provider->GetSurfaceDescription(provider.data(), &surfaceDescription)) != DFB_OK) { - DirectFBError("QDirectFBPixmapData::fromDataBufferDescription(): Can't get surface description", result); - return false; - } - DFBImageDescription imageDescription; result = provider->GetImageDescription(provider.data(), &imageDescription); if (result != DFB_OK) { @@ -264,7 +258,17 @@ bool QDirectFBPixmapData::fromDataBufferDescription(const DFBDataBufferDescripti return false; } - alpha = imageDescription.caps & (DICAPS_ALPHACHANNEL|DICAPS_COLORKEY); + if (imageDescription.caps & DICAPS_COLORKEY) { + return false; + } + + DFBSurfaceDescription surfaceDescription; + if ((result = provider->GetSurfaceDescription(provider.data(), &surfaceDescription)) != DFB_OK) { + DirectFBError("QDirectFBPixmapData::fromDataBufferDescription(): Can't get surface description", result); + return false; + } + + alpha = imageDescription.caps & DICAPS_ALPHACHANNEL; imageFormat = alpha ? screen->alphaPixmapFormat() : screen->pixelFormat(); dfbSurface = screen->createDFBSurface(QSize(surfaceDescription.width, surfaceDescription.height), diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp index bf6164d..f2ee6ae 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp @@ -1554,9 +1554,8 @@ void QDirectFBScreen::exposeRegion(QRegion r, int) : (DSBLIT_BLEND_ALPHACHANNEL|DSBLIT_BLEND_COLORALPHA); } } - if (!region.isEmpty()) { - solidFill(d_ptr->backgroundColor, region); - } + + solidFill(d_ptr->backgroundColor, region); while (idx > 0) { const PaintCommand &cmd = commands[--idx]; @@ -1629,29 +1628,34 @@ void QDirectFBScreen::solidFill(const QColor &color, const QRegion ®ion) Q_UNUSED(color); Q_UNUSED(region); #else + QDirectFBScreen::solidFill(d_ptr->primarySurface, color, region); +#endif +} + +static inline void clearRect(IDirectFBSurface *surface, const QColor &color, const QRect &rect) +{ + Q_ASSERT(surface); + const DFBRegion region = { rect.left(), rect.top(), rect.right(), rect.bottom() }; + // could just reinterpret_cast this to a DFBRegion + surface->SetClip(surface, ®ion); + surface->Clear(surface, color.red(), color.green(), color.blue(), color.alpha()); +} + +void QDirectFBScreen::solidFill(IDirectFBSurface *surface, const QColor &color, const QRegion ®ion) +{ if (region.isEmpty()) return; - d_ptr->primarySurface->SetColor(d_ptr->primarySurface, - color.red(), color.green(), color.blue(), - color.alpha()); const int n = region.rectCount(); if (n == 1) { - const QRect r = region.boundingRect(); - d_ptr->primarySurface->FillRectangle(d_ptr->primarySurface, r.x(), r.y(), r.width(), r.height()); + clearRect(surface, color, region.boundingRect()); } else { const QVector<QRect> rects = region.rects(); - QVarLengthArray<DFBRectangle, 32> rectArray(n); for (int i=0; i<n; ++i) { - const QRect &r = rects.at(i); - rectArray[i].x = r.x(); - rectArray[i].y = r.y(); - rectArray[i].w = r.width(); - rectArray[i].h = r.height(); + clearRect(surface, color, rects.at(i)); } - d_ptr->primarySurface->FillRectangles(d_ptr->primarySurface, rectArray.constData(), n); } -#endif + surface->SetClip(surface, 0); } QImage::Format QDirectFBScreen::alphaPixmapFormat() const diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.h b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.h index c483020..1085423 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.h +++ b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.h @@ -159,6 +159,7 @@ public: void exposeRegion(QRegion r, int changing); void solidFill(const QColor &color, const QRegion ®ion); + static void solidFill(IDirectFBSurface *surface, const QColor &color, const QRegion ®ion); void setMode(int width, int height, int depth); void blank(bool on); diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp index 51969fc..2eeee24 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp @@ -380,11 +380,18 @@ void QDirectFBWindowSurface::flush(QWidget *widget, const QRegion ®ion, flushPending = false; } -void QDirectFBWindowSurface::beginPaint(const QRegion &) +void QDirectFBWindowSurface::beginPaint(const QRegion ®ion) { if (!engine) { engine = new QDirectFBPaintEngine(this); } + + if (dfbSurface) { + const QWidget *win = window(); + if (win && win->testAttribute(Qt::WA_NoSystemBackground)) { + QDirectFBScreen::solidFill(dfbSurface, Qt::transparent, region); + } + } flushPending = true; } diff --git a/src/plugins/graphicssystems/meego/dithering.cpp b/src/plugins/graphicssystems/meego/dithering.cpp new file mode 100644 index 0000000..b50826c --- /dev/null +++ b/src/plugins/graphicssystems/meego/dithering.cpp @@ -0,0 +1,277 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +// This is an implementation of the 32bit => 16bit Floyd-Steinberg dithering. +// The alghorithm used here is not the fastest possible but it's prolly fast enough: +// uses look-up tables, integer-only arthmetics and works in one pass on two lines +// at a time. It's a high-quality dithering using 1/8 diffusion precission. +// Two functions here to look at: +// +// * convertRGBA32_to_RGB565 +// * convertRGBA32_to_RGBA4444 +// +// Each channel (RGBA) is diffused independently and alpha is dithered too. + +#include <string.h> +#include <stdio.h> +#include <stdlib.h> +#include <math.h> +#include <QVarLengthArray> + +// Gets a component (red = 1, green = 2...) from a RGBA data structure. +// data is unsigned char. stride is the number of bytes per line. +#define GET_RGBA_COMPONENT(data, x, y, stride, c) (data[(y * stride) + (x << 2) + c]) + +// Writes a new pixel with r, g, b to data in 565 16bit format. Data is a short. +#define PUT_565(data, x, y, width, r, g, b) (data[(y * width) + x] = (r << 11) | (g << 5) | b) + +// Writes a new pixel with r, g, b, a to data in 4444 RGBA 16bit format. Data is a short. +#define PUT_4444(data, x, y, width, r, g, b, a) (data[(y * width) + x] = (r << 12) | (g << 8) | (b << 4) | a) + +// Writes(ads) a new value to the diffusion accumulator. accumulator is a short. +// x, y is a position in the accumulation buffer. y can be 0 or 1 -- we operate on two lines at time. +#define ACCUMULATE(accumulator, x, y, width, v) if (x < width && x > 0) accumulator[(y * width) + x] += v + +// Clamps a value to be in 0..255 range. +#define CLAMP_256(v) if (v > 255) v = 255; if (v < 0) v = 0; + +// Converts incoming RGB32 (QImage::Format_RGB32) to RGB565. Returns the newly allocated data. +unsigned short* convertRGB32_to_RGB565(const unsigned char *in, int width, int height, int stride) +{ + // Will store output + unsigned short *out = (unsigned short *) malloc(width * height * 2); + + // Lookup tables for the 8bit => 6bit and 8bit => 5bit conversion + unsigned char lookup_8bit_to_5bit[256]; + short lookup_8bit_to_5bit_diff[256]; + unsigned char lookup_8bit_to_6bit[256]; + short lookup_8bit_to_6bit_diff[256]; + + // Macros for the conversion using the lookup table. + #define CONVERT_8BIT_TO_5BIT(v) (lookup_8bit_to_5bit[v]) + #define DIFF_8BIT_TO_5BIT(v) (lookup_8bit_to_5bit_diff[v]) + + #define CONVERT_8BIT_TO_6BIT(v) (lookup_8bit_to_6bit[v]) + #define DIFF_8BIT_TO_6BIT(v) (lookup_8bit_to_6bit_diff[v]) + + int i; + int x, y, c; // Pixel we're processing. c is component number (0, 1, 2 for r, b, b) + short component[3]; // Stores the new components (r, g, b) for pixel produced during conversion + short diff; // The difference between the converted value and the original one. To be accumulated. + QVarLengthArray <short> accumulatorData(3 * width * 2); // Data for three acumulators for r, g, b. Each accumulator is two lines. + short *accumulator[3]; // Helper for accessing the accumulator on a per-channel basis more easily. + accumulator[0] = accumulatorData.data(); + accumulator[1] = accumulatorData.data() + width; + accumulator[2] = accumulatorData.data() + (width * 2); + + // Produce the conversion lookup tables. + for (i = 0; i < 256; i++) { + lookup_8bit_to_5bit[i] = round(i / 8.0); + if (lookup_8bit_to_5bit[i] > 31) + lookup_8bit_to_5bit[i] -= 1; + + // Before bitshifts: (i * 8) - (... * 8 * 8) + lookup_8bit_to_5bit_diff[i] = (i << 3) - (lookup_8bit_to_5bit[i] << 6); + + lookup_8bit_to_6bit[i] = round(i / 4.0); + if (lookup_8bit_to_6bit[i] > 63) + lookup_8bit_to_6bit[i] -= 1; + + // Before bitshifts: (i * 8) - (... * 4 * 8) + lookup_8bit_to_6bit_diff[i] = (i << 3) - (lookup_8bit_to_6bit[i] << 5); + } + + // Clear the accumulators + memset(accumulator[0], 0, width * 4); + memset(accumulator[1], 0, width * 4); + memset(accumulator[2], 0, width * 4); + + // For each line... + for (y = 0; y < height; y++) { + + // For each accumulator, move the second line (index 1) to replace the first line (index 0). + // Clear the second line (index 1) + memcpy(accumulator[0], accumulator[0] + width, width * 2); + memset(accumulator[0] + width, 0, width * 2); + + memcpy(accumulator[1], accumulator[1] + width, width * 2); + memset(accumulator[1] + width, 0, width * 2); + + memcpy(accumulator[2], accumulator[2] + width, width * 2); + memset(accumulator[2] + width, 0, width * 2); + + // For each column.... + for (x = 0; x < width; x++) { + + // For each component (r, g, b)... + for (c = 0; c < 3; c++) { + + // Get the 8bit value from the original image + component[c] = GET_RGBA_COMPONENT(in, x, y, stride, c); + + // Add the diffusion for this pixel we stored in the accumulator. + // >> 7 because the values in accumulator are stored * 128 + component[c] += accumulator[c][x] >> 7; + + // Make sure we're not over the boundaries. + CLAMP_256(component[c]); + + // For green component we use 6 bits. Otherwise 5 bits. + // Store the difference from converting 8bit => 6 bit and the orig pixel. + // Convert 8bit => 6(5) bit. + if (c == 1) { + diff = DIFF_8BIT_TO_6BIT(component[c]); + component[c] = CONVERT_8BIT_TO_6BIT(component[c]); + } else { + diff = DIFF_8BIT_TO_5BIT(component[c]); + component[c] = CONVERT_8BIT_TO_5BIT(component[c]); + } + + // Distribute the difference according to the matrix in the + // accumulation bufffer. + ACCUMULATE(accumulator[c], x + 1, 0, width, diff * 7); + ACCUMULATE(accumulator[c], x - 1, 1, width, diff * 3); + ACCUMULATE(accumulator[c], x, 1, width, diff * 5); + ACCUMULATE(accumulator[c], x + 1, 1, width, diff * 1); + } + + // Write the newly produced pixel + PUT_565(out, x, y, width, component[2], component[1], component[0]); + } + } + + return out; +} + +// Converts incoming RGBA32 (QImage::Format_ARGB32_Premultiplied) to RGB565. Returns the newly allocated data. +// This function is similar (yet different) to the _565 variant but it makes sense to duplicate it here for simplicity. +unsigned short* convertARGB32_to_RGBA4444(const unsigned char *in, int width, int height, int stride) +{ + // Will store output + unsigned short *out = (unsigned short *) malloc(width * height * 2); + + // Lookup tables for the 8bit => 4bit conversion + unsigned char lookup_8bit_to_4bit[256]; + short lookup_8bit_to_4bit_diff[256]; + + // Macros for the conversion using the lookup table. + #define CONVERT_8BIT_TO_4BIT(v) (lookup_8bit_to_4bit[v]) + #define DIFF_8BIT_TO_4BIT(v) (lookup_8bit_to_4bit_diff[v]) + + int i; + int x, y, c; // Pixel we're processing. c is component number (0, 1, 2, 3 for r, b, b, a) + short component[4]; // Stores the new components (r, g, b, a) for pixel produced during conversion + short diff; // The difference between the converted value and the original one. To be accumulated. + QVarLengthArray <short> accumulatorData(4 * width * 2); // Data for three acumulators for r, g, b. Each accumulator is two lines. + short *accumulator[4]; // Helper for accessing the accumulator on a per-channel basis more easily. + accumulator[0] = accumulatorData.data(); + accumulator[1] = accumulatorData.data() + width; + accumulator[2] = accumulatorData.data() + (width * 2); + accumulator[3] = accumulatorData.data() + (width * 3); + + // Produce the conversion lookup tables. + for (i = 0; i < 256; i++) { + lookup_8bit_to_4bit[i] = round(i / 16.0); + if (lookup_8bit_to_4bit[i] > 15) + lookup_8bit_to_4bit[i] -= 1; + + // Before bitshifts: (i * 8) - (... * 16 * 8) + lookup_8bit_to_4bit_diff[i] = (i << 3) - (lookup_8bit_to_4bit[i] << 7); + } + + // Clear the accumulators + memset(accumulator[0], 0, width * 4); + memset(accumulator[1], 0, width * 4); + memset(accumulator[2], 0, width * 4); + memset(accumulator[3], 0, width * 4); + + // For each line... + for (y = 0; y < height; y++) { + + // For each component (r, g, b, a)... + memcpy(accumulator[0], accumulator[0] + width, width * 2); + memset(accumulator[0] + width, 0, width * 2); + + memcpy(accumulator[1], accumulator[1] + width, width * 2); + memset(accumulator[1] + width, 0, width * 2); + + memcpy(accumulator[2], accumulator[2] + width, width * 2); + memset(accumulator[2] + width, 0, width * 2); + + memcpy(accumulator[3], accumulator[3] + width, width * 2); + memset(accumulator[3] + width, 0, width * 2); + + // For each column.... + for (x = 0; x < width; x++) { + + // For each component (r, g, b, a)... + for (c = 0; c < 4; c++) { + + // Get the 8bit value from the original image + component[c] = GET_RGBA_COMPONENT(in, x, y, stride, c); + + // Add the diffusion for this pixel we stored in the accumulator. + // >> 7 because the values in accumulator are stored * 128 + component[c] += accumulator[c][x] >> 7; + + // Make sure we're not over the boundaries. + CLAMP_256(component[c]); + + // Store the difference from converting 8bit => 4bit and the orig pixel. + // Convert 8bit => 4bit. + diff = DIFF_8BIT_TO_4BIT(component[c]); + component[c] = CONVERT_8BIT_TO_4BIT(component[c]); + + // Distribute the difference according to the matrix in the + // accumulation bufffer. + ACCUMULATE(accumulator[c], x + 1, 0, width, diff * 7); + ACCUMULATE(accumulator[c], x - 1, 1, width, diff * 3); + ACCUMULATE(accumulator[c], x, 1, width, diff * 5); + ACCUMULATE(accumulator[c], x + 1, 1, width, diff * 1); + } + + // Write the newly produced pixel + PUT_4444(out, x, y, width, component[0], component[1], component[2], component[3]); + } + } + + return out; +} diff --git a/src/plugins/graphicssystems/meego/meego.pro b/src/plugins/graphicssystems/meego/meego.pro index d750d34..0d3cce6 100644 --- a/src/plugins/graphicssystems/meego/meego.pro +++ b/src/plugins/graphicssystems/meego/meego.pro @@ -5,8 +5,8 @@ QT += gui opengl QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/graphicssystems -HEADERS = qmeegographicssystem.h qmeegopixmapdata.h qmeegoextensions.h -SOURCES = qmeegographicssystem.cpp qmeegographicssystem.h qmeegographicssystemplugin.h qmeegographicssystemplugin.cpp qmeegopixmapdata.h qmeegopixmapdata.cpp qmeegoextensions.h qmeegoextensions.cpp +HEADERS = qmeegographicssystem.h qmeegopixmapdata.h qmeegoextensions.h qmeegorasterpixmapdata.h qmeegolivepixmapdata.h +SOURCES = qmeegographicssystem.cpp qmeegographicssystem.h qmeegographicssystemplugin.h qmeegographicssystemplugin.cpp qmeegopixmapdata.h qmeegopixmapdata.cpp qmeegoextensions.h qmeegoextensions.cpp qmeegorasterpixmapdata.h qmeegorasterpixmapdata.cpp qmeegolivepixmapdata.cpp qmeegolivepixmapdata.h dithering.cpp target.path += $$[QT_INSTALL_PLUGINS]/graphicssystems INSTALLS += target diff --git a/src/plugins/graphicssystems/meego/qmeegographicssystem.cpp b/src/plugins/graphicssystems/meego/qmeegographicssystem.cpp index f8b228c..a633e2f 100644 --- a/src/plugins/graphicssystems/meego/qmeegographicssystem.cpp +++ b/src/plugins/graphicssystems/meego/qmeegographicssystem.cpp @@ -54,6 +54,7 @@ #include <private/qpixmap_x11_p.h> #include "qmeegopixmapdata.h" +#include "qmeegolivepixmapdata.h" #include "qmeegographicssystem.h" #include "qmeegoextensions.h" @@ -150,8 +151,8 @@ void QMeeGoGraphicsSystem::setTranslucent(bool translucent) QPixmapData *QMeeGoGraphicsSystem::pixmapDataFromEGLSharedImage(Qt::HANDLE handle, const QImage &softImage) { if (softImage.format() != QImage::Format_ARGB32_Premultiplied && - softImage.format() != QImage::Format_ARGB32) { - qFatal("For egl shared images, the soft image has to be ARGB32 or ARGB32_Premultiplied"); + softImage.format() != QImage::Format_RGB32) { + qFatal("For egl shared images, the soft image has to be ARGB32_Premultiplied or RGB32"); return NULL; } @@ -173,22 +174,6 @@ QPixmapData *QMeeGoGraphicsSystem::pixmapDataFromEGLSharedImage(Qt::HANDLE handl } } -QPixmapData *QMeeGoGraphicsSystem::pixmapDataFromEGLImage(Qt::HANDLE handle) -{ - if (QMeeGoGraphicsSystem::meeGoRunning()) { - QMeeGoPixmapData *pmd = new QMeeGoPixmapData; - pmd->fromEGLImage(handle); - - // FIXME Ok. This is a bit BAD BAD BAD. We're abusing here the fact that we KNOW - // that this function is used for the live pixmap... - pmd->texture()->options &= ~QGLContext::InvertedYBindOption; - return QMeeGoGraphicsSystem::wrapPixmapData(pmd); - } else { - qFatal("Can't create from EGL image when not running meego graphics system!"); - return NULL; - } -} - void QMeeGoGraphicsSystem::updateEGLSharedImagePixmap(QPixmap *pixmap) { QMeeGoPixmapData *pmd = (QMeeGoPixmapData *) pixmap->pixmapData(); @@ -207,109 +192,6 @@ QPixmapData *QMeeGoGraphicsSystem::pixmapDataWithGLTexture(int w, int h) return QMeeGoGraphicsSystem::wrapPixmapData(pmd); } -Qt::HANDLE QMeeGoGraphicsSystem::createLiveTexture(int w, int h, QImage::Format format) -{ - // No need to wrap the QPixmapData here. This QPixmap(Data) is a - // internal implementation and we don't migrate it between - // graphics system switching. - - // We use a bit ugly way of enforcing a color format on the X pixmap -- we create - // a local QImage and fromImage from there. This is quite redundant (extra overhead of creating - // the useless image only to delete it) but shouldn't be too bad for now... you're not expected - // to call createLiveTexture too often anyways. Would be great if QX11PixmapData had a way to - // force the X format upon creation or resize. - - QImage image(w, h, format); - QX11PixmapData *pmd = new QX11PixmapData(QPixmapData::PixmapType); - pmd->fromImage(image, Qt::NoOpaqueDetection); - QPixmap *p = new QPixmap(pmd); - - liveTexturePixmaps.insert(p->handle(), p); - return p->handle(); -} - -void QMeeGoGraphicsSystem::destroyLiveTexture(Qt::HANDLE h) -{ - if (liveTexturePixmaps.contains(h)) { - QPixmap *p = liveTexturePixmaps.value(h); - delete p; - liveTexturePixmaps.remove(h); - } else - qWarning("Trying to destroy live texture %ld which was not found!", h); -} - -bool QMeeGoGraphicsSystem::lockLiveTexture(Qt::HANDLE h) -{ - if (! liveTexturePixmaps.contains(h)) { - qWarning("Trying to lock live texture %ld which was not found!", h); - return false; - } - - EGLint attribs[] = { - EGL_MAP_PRESERVE_PIXELS_KHR, EGL_TRUE, - EGL_LOCK_USAGE_HINT_KHR, EGL_READ_SURFACE_BIT_KHR | EGL_WRITE_SURFACE_BIT_KHR, - EGL_NONE - }; - - QGLShareContextScope ctx(qt_gl_share_widget()->context()); - EGLSurface surface = getSurfaceForLiveTexturePixmap(liveTexturePixmaps.value(h)); - return QMeeGoExtensions::eglLockSurfaceKHR(QEgl::display(), surface, attribs); -} - -bool QMeeGoGraphicsSystem::unlockLiveTexture(Qt::HANDLE h) -{ - if (! liveTexturePixmaps.contains(h)) { - qWarning("Trying to lock live texture %ld which was not found!", h); - return false; - } - - QGLShareContextScope ctx(qt_gl_share_widget()->context()); - QMeeGoExtensions::ensureInitialized(); - - EGLSurface surface = getSurfaceForLiveTexturePixmap(liveTexturePixmaps.value(h)); - if (QMeeGoExtensions::eglUnlockSurfaceKHR(QEgl::display(), surface)) { - glFinish(); - return true; - } else { - return false; - } -} - -void QMeeGoGraphicsSystem::queryLiveTexture(Qt::HANDLE h, void **data, int *pitch) -{ - // FIXME Only allow this on locked surfaces - if (! liveTexturePixmaps.contains(h)) { - qWarning("Trying to query live texture %ld which was not found!", h); - return; - } - - QGLShareContextScope ctx(qt_gl_share_widget()->context()); - QMeeGoExtensions::ensureInitialized(); - - EGLSurface surface = getSurfaceForLiveTexturePixmap(liveTexturePixmaps.value(h)); - eglQuerySurface(QEgl::display(), surface, EGL_BITMAP_POINTER_KHR, (EGLint*) data); - eglQuerySurface(QEgl::display(), surface, EGL_BITMAP_PITCH_KHR, (EGLint*) pitch); -} - -Qt::HANDLE QMeeGoGraphicsSystem::liveTextureToEGLImage(Qt::HANDLE h) -{ - QGLShareContextScope ctx(qt_gl_share_widget()->context()); - QMeeGoExtensions::ensureInitialized(); - - EGLint attribs[] = { - EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, - EGL_NONE - }; - - EGLImageKHR eglImage = QEgl::eglCreateImageKHR(QEgl::display(), EGL_NO_CONTEXT, EGL_NATIVE_PIXMAP_KHR, - (EGLClientBuffer) h, attribs); - - if (eglImage == EGL_NO_IMAGE_KHR) - qWarning("eglCreateImageKHR failed!"); - - return (Qt::HANDLE) eglImage; -} - bool QMeeGoGraphicsSystem::meeGoRunning() { if (! QApplicationPrivate::instance()) { @@ -326,50 +208,32 @@ bool QMeeGoGraphicsSystem::meeGoRunning() return (name == "meego"); } -void QMeeGoGraphicsSystem::destroySurfaceForLiveTexturePixmap(QPixmapData* pmd) +QPixmapData* QMeeGoGraphicsSystem::pixmapDataWithNewLiveTexture(int w, int h, QImage::Format format) { - Q_ASSERT(pmd->classId() == QPixmapData::X11Class); - QX11PixmapData *pixmapData = static_cast<QX11PixmapData*>(pmd); - if (pixmapData->gl_surface) { - eglDestroySurface(QEgl::display(), (EGLSurface)pixmapData->gl_surface); - pixmapData->gl_surface = 0; - } + return new QMeeGoLivePixmapData(w, h, format); } -EGLSurface QMeeGoGraphicsSystem::getSurfaceForLiveTexturePixmap(QPixmap *pixmap) +QPixmapData* QMeeGoGraphicsSystem::pixmapDataFromLiveTextureHandle(Qt::HANDLE handle) { - // This code is a crative remix of the stuff that can be found in the - // Qt's TFP implementation in /src/opengl/qgl_x11egl.cpp ::bindiTextureFromNativePixmap - QX11PixmapData *pixmapData = static_cast<QX11PixmapData*>(pixmap->data_ptr().data()); - Q_ASSERT(pixmapData->classId() == QPixmapData::X11Class); - bool hasAlpha = pixmapData->hasAlphaChannel(); - - if (pixmapData->gl_surface && - hasAlpha == (pixmapData->flags & QX11PixmapData::GlSurfaceCreatedWithAlpha)) - return pixmapData->gl_surface; - - // Check to see if the surface is still valid - if (pixmapData->gl_surface && - hasAlpha != ((pixmapData->flags & QX11PixmapData::GlSurfaceCreatedWithAlpha) > 0)) { - // Surface is invalid! - QMeeGoGraphicsSystem::destroySurfaceForLiveTexturePixmap(pixmapData); - } + return new QMeeGoLivePixmapData(handle); +} - if (pixmapData->gl_surface == 0) { - EGLConfig config = QEgl::defaultConfig(QInternal::Pixmap, - QEgl::OpenGL, - hasAlpha ? QEgl::Translucent : QEgl::NoOptions); +QImage* QMeeGoGraphicsSystem::lockLiveTexture(QPixmap* pixmap) +{ + QMeeGoLivePixmapData *pixmapData = static_cast<QMeeGoLivePixmapData*>(pixmap->data_ptr().data()); + return pixmapData->lock(); +} - pixmapData->gl_surface = (void*)QEgl::createSurface(pixmap, config); - - if (hasAlpha) - pixmapData->flags = pixmapData->flags | QX11PixmapData::GlSurfaceCreatedWithAlpha; - - if (pixmapData->gl_surface == (void*)EGL_NO_SURFACE) - return NULL; - } +bool QMeeGoGraphicsSystem::releaseLiveTexture(QPixmap *pixmap, QImage *image) +{ + QMeeGoLivePixmapData *pixmapData = static_cast<QMeeGoLivePixmapData*>(pixmap->data_ptr().data()); + return pixmapData->release(image); +} - return pixmapData->gl_surface; +Qt::HANDLE QMeeGoGraphicsSystem::getLiveTextureHandle(QPixmap *pixmap) +{ + QMeeGoLivePixmapData *pixmapData = static_cast<QMeeGoLivePixmapData*>(pixmap->data_ptr().data()); + return pixmapData->handle(); } /* C API */ @@ -384,11 +248,6 @@ QPixmapData* qt_meego_pixmapdata_from_egl_shared_image(Qt::HANDLE handle, const return QMeeGoGraphicsSystem::pixmapDataFromEGLSharedImage(handle, softImage); } -QPixmapData* qt_meego_pixmapdata_from_egl_image(Qt::HANDLE handle) -{ - return QMeeGoGraphicsSystem::pixmapDataFromEGLImage(handle); -} - QPixmapData* qt_meego_pixmapdata_with_gl_texture(int w, int h) { return QMeeGoGraphicsSystem::pixmapDataWithGLTexture(w, h); @@ -419,32 +278,27 @@ void qt_meego_update_egl_shared_image_pixmap(QPixmap *pixmap) QMeeGoGraphicsSystem::updateEGLSharedImagePixmap(pixmap); } -Qt::HANDLE qt_meego_live_texture_create(int w, int h, QImage::Format format) +QPixmapData* qt_meego_pixmapdata_with_new_live_texture(int w, int h, QImage::Format format) { - return QMeeGoGraphicsSystem::createLiveTexture(w, h, format); + return QMeeGoGraphicsSystem::pixmapDataWithNewLiveTexture(w, h, format); } -void qt_meego_live_texture_destroy(Qt::HANDLE h) +QPixmapData* qt_meego_pixmapdata_from_live_texture_handle(Qt::HANDLE handle) { - QMeeGoGraphicsSystem::destroyLiveTexture(h); + return QMeeGoGraphicsSystem::pixmapDataFromLiveTextureHandle(handle); } -bool qt_meego_live_texture_lock(Qt::HANDLE h) +QImage* qt_meego_live_texture_lock(QPixmap *pixmap) { - return QMeeGoGraphicsSystem::lockLiveTexture(h); + return QMeeGoGraphicsSystem::lockLiveTexture(pixmap); } -bool qt_meego_live_texture_unlock(Qt::HANDLE h) +bool qt_meego_live_texture_release(QPixmap *pixmap, QImage *image) { - return QMeeGoGraphicsSystem::unlockLiveTexture(h); + return QMeeGoGraphicsSystem::releaseLiveTexture(pixmap, image); } -void qt_meego_live_texture_query(Qt::HANDLE h, void **data, int *pitch) +Qt::HANDLE qt_meego_live_texture_get_handle(QPixmap *pixmap) { - return QMeeGoGraphicsSystem::queryLiveTexture(h, data, pitch); -} - -Qt::HANDLE qt_meego_live_texture_to_egl_image(Qt::HANDLE h) -{ - return QMeeGoGraphicsSystem::liveTextureToEGLImage(h); -} + return QMeeGoGraphicsSystem::getLiveTextureHandle(pixmap); +}
\ No newline at end of file diff --git a/src/plugins/graphicssystems/meego/qmeegographicssystem.h b/src/plugins/graphicssystems/meego/qmeegographicssystem.h index 934d32d..2697f0f 100644 --- a/src/plugins/graphicssystems/meego/qmeegographicssystem.h +++ b/src/plugins/graphicssystems/meego/qmeegographicssystem.h @@ -67,12 +67,11 @@ public: static QPixmapData *pixmapDataWithGLTexture(int w, int h); static void updateEGLSharedImagePixmap(QPixmap *pixmap); - static Qt::HANDLE createLiveTexture(int w, int h, QImage::Format format); - static void destroyLiveTexture(Qt::HANDLE h); - static bool lockLiveTexture(Qt::HANDLE h); - static bool unlockLiveTexture(Qt::HANDLE h); - static void queryLiveTexture(Qt::HANDLE h, void **data, int *pitch); - static Qt::HANDLE liveTextureToEGLImage(Qt::HANDLE h); + static QPixmapData *pixmapDataWithNewLiveTexture(int w, int h, QImage::Format format); + static QPixmapData *pixmapDataFromLiveTextureHandle(Qt::HANDLE handle); + static QImage *lockLiveTexture(QPixmap* pixmap); + static bool releaseLiveTexture(QPixmap *pixmap, QImage *image); + static Qt::HANDLE getLiveTextureHandle(QPixmap *pixmap); private: static bool meeGoRunning(); @@ -88,19 +87,17 @@ private: extern "C" { Q_DECL_EXPORT int qt_meego_image_to_egl_shared_image(const QImage &image); Q_DECL_EXPORT QPixmapData* qt_meego_pixmapdata_from_egl_shared_image(Qt::HANDLE handle, const QImage &softImage); - Q_DECL_EXPORT QPixmapData* qt_meego_pixmapdata_from_egl_image(Qt::HANDLE handle); Q_DECL_EXPORT QPixmapData* qt_meego_pixmapdata_with_gl_texture(int w, int h); Q_DECL_EXPORT void qt_meego_update_egl_shared_image_pixmap(QPixmap *pixmap); Q_DECL_EXPORT bool qt_meego_destroy_egl_shared_image(Qt::HANDLE handle); Q_DECL_EXPORT void qt_meego_set_surface_fixed_size(int width, int height); Q_DECL_EXPORT void qt_meego_set_surface_scaling(int x, int y, int width, int height); - Q_DECL_EXPORT void qt_meego_set_translucent(bool translucent); - Q_DECL_EXPORT Qt::HANDLE m_live_texture_create(int w, int h, QImage::Format format); - Q_DECL_EXPORT void m_live_texture_destroy(Qt::HANDLE h); - Q_DECL_EXPORT bool m_live_texture_lock(Qt::HANDLE h); - Q_DECL_EXPORT bool m_live_texture_unlock(Qt::HANDLE h); - Q_DECL_EXPORT void m_live_texture_query(Qt::HANDLE h, void **data, int *pitch); - Q_DECL_EXPORT Qt::HANDLE m_live_texture_to_egl_image(Qt::HANDLE h); + Q_DECL_EXPORT void qt_meego_set_translucent(bool translucent); + Q_DECL_EXPORT QPixmapData* qt_meego_pixmapdata_with_new_live_texture(int w, int h, QImage::Format format); + Q_DECL_EXPORT QPixmapData* qt_meego_pixmapdata_from_live_texture_handle(Qt::HANDLE handle); + Q_DECL_EXPORT QImage* qt_meego_live_texture_lock(QPixmap *pixmap); + Q_DECL_EXPORT bool qt_meego_live_texture_release(QPixmap *pixmap, QImage *image); + Q_DECL_EXPORT Qt::HANDLE qt_meego_live_texture_get_handle(QPixmap *pixmap); } #endif diff --git a/src/plugins/graphicssystems/meego/qmeegolivepixmapdata.cpp b/src/plugins/graphicssystems/meego/qmeegolivepixmapdata.cpp new file mode 100644 index 0000000..405b765 --- /dev/null +++ b/src/plugins/graphicssystems/meego/qmeegolivepixmapdata.cpp @@ -0,0 +1,287 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qmeegolivepixmapdata.h" +#include "qmeegoextensions.h" +#include "qmeegorasterpixmapdata.h" +#include <private/qimage_p.h> +#include <private/qwindowsurface_gl_p.h> +#include <private/qeglcontext_p.h> +#include <private/qapplication_p.h> +#include <private/qgraphicssystem_runtime_p.h> +#include <private/qpixmap_x11_p.h> +#include <stdio.h> + +static EGLint lock_attribs[] = { + EGL_MAP_PRESERVE_PIXELS_KHR, EGL_TRUE, + EGL_LOCK_USAGE_HINT_KHR, EGL_READ_SURFACE_BIT_KHR | EGL_WRITE_SURFACE_BIT_KHR, + EGL_NONE +}; + +static EGLint preserved_attribs[] = { + EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, + EGL_NONE +}; + +// as copied from qwindowsurface.cpp +void qt_scrollRectInImage(QImage &img, const QRect &rect, const QPoint &offset) +{ + // make sure we don't detach + uchar *mem = const_cast<uchar*>(const_cast<const QImage &>(img).bits()); + + int lineskip = img.bytesPerLine(); + int depth = img.depth() >> 3; + + const QRect imageRect(0, 0, img.width(), img.height()); + const QRect r = rect & imageRect & imageRect.translated(-offset); + const QPoint p = rect.topLeft() + offset; + + if (r.isEmpty()) + return; + + const uchar *src; + uchar *dest; + + if (r.top() < p.y()) { + src = mem + r.bottom() * lineskip + r.left() * depth; + dest = mem + (p.y() + r.height() - 1) * lineskip + p.x() * depth; + lineskip = -lineskip; + } else { + src = mem + r.top() * lineskip + r.left() * depth; + dest = mem + p.y() * lineskip + p.x() * depth; + } + + const int w = r.width(); + int h = r.height(); + const int bytes = w * depth; + + // overlapping segments? + if (offset.y() == 0 && qAbs(offset.x()) < w) { + do { + ::memmove(dest, src, bytes); + dest += lineskip; + src += lineskip; + } while (--h); + } else { + do { + ::memcpy(dest, src, bytes); + dest += lineskip; + src += lineskip; + } while (--h); + } +} + +/* Public */ + +QMeeGoLivePixmapData::QMeeGoLivePixmapData(int w, int h, QImage::Format format) : QGLPixmapData(QPixmapData::PixmapType) +{ + QImage image(w, h, format); + QX11PixmapData *pmd = new QX11PixmapData(QPixmapData::PixmapType); + pmd->fromImage(image, Qt::NoOpaqueDetection); + backingX11Pixmap = new QPixmap(pmd); + + initializeThroughEGLImage(); +} + +QMeeGoLivePixmapData::QMeeGoLivePixmapData(Qt::HANDLE h) : QGLPixmapData(QPixmapData::PixmapType) +{ + backingX11Pixmap = new QPixmap(QPixmap::fromX11Pixmap(h)); + initializeThroughEGLImage(); +} + +QMeeGoLivePixmapData::~QMeeGoLivePixmapData() +{ + delete backingX11Pixmap; +} + +void QMeeGoLivePixmapData::initializeThroughEGLImage() +{ + QGLShareContextScope ctx(qt_gl_share_widget()->context()); + QMeeGoExtensions::ensureInitialized(); + + EGLImageKHR eglImage = EGL_NO_IMAGE_KHR; + GLuint newTextureId = 0; + + eglImage = QEgl::eglCreateImageKHR(QEgl::display(), EGL_NO_CONTEXT, EGL_NATIVE_PIXMAP_KHR, + (EGLClientBuffer) backingX11Pixmap->handle(), preserved_attribs); + + if (eglImage == EGL_NO_IMAGE_KHR) { + qWarning("eglCreateImageKHR failed (live texture)!"); + return; + } + + glGenTextures(1, &newTextureId); + glBindTexture(GL_TEXTURE_2D, newTextureId); + + glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (EGLImageKHR) eglImage); + if (glGetError() == GL_NO_ERROR) { + resize(backingX11Pixmap->width(), backingX11Pixmap->height()); + texture()->id = newTextureId; + texture()->options &= ~QGLContext::InvertedYBindOption; + m_hasAlpha = backingX11Pixmap->hasAlphaChannel(); + } else { + qWarning("Failed to create a texture from an egl image (live texture)!"); + glDeleteTextures(1, &newTextureId); + } + + QEgl::eglDestroyImageKHR(QEgl::display(), eglImage); +} + +QPixmapData *QMeeGoLivePixmapData::createCompatiblePixmapData() const +{ + qWarning("Create compatible called on live pixmap! Expect fail soon..."); + return new QMeeGoRasterPixmapData(pixelType()); +} + +QImage* QMeeGoLivePixmapData::lock() +{ + QGLShareContextScope ctx(qt_gl_share_widget()->context()); + QMeeGoExtensions::ensureInitialized(); + + void *data = 0; + int pitch = 0; + EGLSurface surface = 0; + QImage::Format format; + lockedImage = QImage(); + + surface = getSurfaceForBackingPixmap(); + if (! QMeeGoExtensions::eglLockSurfaceKHR(QEgl::display(), surface, lock_attribs)) { + qWarning("Failed to lock surface (live texture)!"); + return &lockedImage; + } + + eglQuerySurface(QEgl::display(), surface, EGL_BITMAP_POINTER_KHR, (EGLint*) &data); + eglQuerySurface(QEgl::display(), surface, EGL_BITMAP_PITCH_KHR, (EGLint*) &pitch); + + // Ok, here we know we just support those two formats. Real solution would be: + // uqery also the format. + if (backingX11Pixmap->depth() > 16) + format = QImage::Format_ARGB32_Premultiplied; + else + format = QImage::Format_RGB16; + + if (data == NULL || pitch == 0) { + qWarning("Failed to query the live texture!"); + return &lockedImage; + } + + lockedImage = QImage((uchar *) data, width(), height(), format); + return &lockedImage; +} + +bool QMeeGoLivePixmapData::release(QImage* /*img*/) +{ + QGLShareContextScope ctx(qt_gl_share_widget()->context()); + QMeeGoExtensions::ensureInitialized(); + + if (QMeeGoExtensions::eglUnlockSurfaceKHR(QEgl::display(), getSurfaceForBackingPixmap())) { + lockedImage = QImage(); + glFinish(); + return true; + } else { + lockedImage = QImage(); + return false; + } +} + +Qt::HANDLE QMeeGoLivePixmapData::handle() +{ + return backingX11Pixmap->handle(); +} + +bool QMeeGoLivePixmapData::scroll(int dx, int dy, const QRect &rect) +{ + lock(); + + if (!lockedImage.isNull()) + qt_scrollRectInImage(lockedImage, rect, QPoint(dx, dy)); + + release(&lockedImage); + return true; +} + +EGLSurface QMeeGoLivePixmapData::getSurfaceForBackingPixmap() +{ + // This code is a crative remix of the stuff that can be found in the + // Qt's TFP implementation in /src/opengl/qgl_x11egl.cpp ::bindiTextureFromNativePixmap + QX11PixmapData *pixmapData = static_cast<QX11PixmapData*>(backingX11Pixmap->data_ptr().data()); + Q_ASSERT(pixmapData->classId() == QPixmapData::X11Class); + bool hasAlpha = pixmapData->hasAlphaChannel(); + + if (pixmapData->gl_surface && + hasAlpha == (pixmapData->flags & QX11PixmapData::GlSurfaceCreatedWithAlpha)) + return pixmapData->gl_surface; + + // Check to see if the surface is still valid + if (pixmapData->gl_surface && + hasAlpha != ((pixmapData->flags & QX11PixmapData::GlSurfaceCreatedWithAlpha) > 0)) { + // Surface is invalid! + destroySurfaceForPixmapData(pixmapData); + } + + if (pixmapData->gl_surface == 0) { + EGLConfig config = QEgl::defaultConfig(QInternal::Pixmap, + QEgl::OpenGL, + hasAlpha ? QEgl::Translucent : QEgl::NoOptions); + + pixmapData->gl_surface = (void*)QEgl::createSurface(backingX11Pixmap, config); + + if (hasAlpha) + pixmapData->flags |= QX11PixmapData::GlSurfaceCreatedWithAlpha; + else + pixmapData->flags &= ~QX11PixmapData::GlSurfaceCreatedWithAlpha; + + if (pixmapData->gl_surface == (void*)EGL_NO_SURFACE) + return NULL; + } + + return pixmapData->gl_surface; +} + +void QMeeGoLivePixmapData::destroySurfaceForPixmapData(QPixmapData* pmd) +{ + Q_ASSERT(pmd->classId() == QPixmapData::X11Class); + QX11PixmapData *pixmapData = static_cast<QX11PixmapData*>(pmd); + if (pixmapData->gl_surface) { + eglDestroySurface(QEgl::display(), (EGLSurface)pixmapData->gl_surface); + pixmapData->gl_surface = 0; + } +} diff --git a/src/plugins/graphicssystems/meego/qmeegolivepixmapdata.h b/src/plugins/graphicssystems/meego/qmeegolivepixmapdata.h new file mode 100644 index 0000000..1d647f0 --- /dev/null +++ b/src/plugins/graphicssystems/meego/qmeegolivepixmapdata.h @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef MLIVEPIXMAPDATA_H +#define MLIVEPIXMAPDATA_H + +#include <private/qpixmapdata_gl_p.h> + +class QMeeGoLivePixmapData : public QGLPixmapData +{ +public: + QMeeGoLivePixmapData(int w, int h, QImage::Format format); + QMeeGoLivePixmapData(Qt::HANDLE h); + ~QMeeGoLivePixmapData(); + + QPixmapData *createCompatiblePixmapData() const; + bool scroll(int dx, int dy, const QRect &rect); + + void initializeThroughEGLImage(); + + QImage* lock(); + bool release(QImage *img); + Qt::HANDLE handle(); + + EGLSurface getSurfaceForBackingPixmap(); + void destroySurfaceForPixmapData(QPixmapData* pmd); + + QPixmap *backingX11Pixmap; + QImage lockedImage; +}; + +#endif diff --git a/src/plugins/graphicssystems/meego/qmeegopixmapdata.cpp b/src/plugins/graphicssystems/meego/qmeegopixmapdata.cpp index 84fc593..02a4273 100644 --- a/src/plugins/graphicssystems/meego/qmeegopixmapdata.cpp +++ b/src/plugins/graphicssystems/meego/qmeegopixmapdata.cpp @@ -41,12 +41,17 @@ #include "qmeegopixmapdata.h" #include "qmeegoextensions.h" +#include "qmeegorasterpixmapdata.h" #include <private/qimage_p.h> #include <private/qwindowsurface_gl_p.h> #include <private/qeglcontext_p.h> #include <private/qapplication_p.h> #include <private/qgraphicssystem_runtime_p.h> +// from dithering.cpp +extern unsigned short* convertRGB32_to_RGB565(const unsigned char *in, int width, int height, int stride); +extern unsigned short* convertARGB32_to_RGBA4444(const unsigned char *in, int width, int height, int stride); + static EGLint preserved_image_attribs[] = { EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE }; QHash <void*, QMeeGoImageInfo*> QMeeGoPixmapData::sharedImagesMap; @@ -87,36 +92,6 @@ void QMeeGoPixmapData::fromImage(const QImage &image, } } -void QMeeGoPixmapData::fromEGLImage(Qt::HANDLE handle) -{ - QGLShareContextScope ctx(qt_gl_share_widget()->context()); - QMeeGoExtensions::ensureInitialized(); - - bool textureIsBound = false; - GLuint newTextureId; - GLint newWidth, newHeight; - - glGenTextures(1, &newTextureId); - glBindTexture(GL_TEXTURE_2D, newTextureId); - - glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (EGLImageKHR) handle); - GLint err = glGetError(); - if (err == GL_NO_ERROR) - textureIsBound = true; - - QMeeGoExtensions::eglQueryImageNOK(QEgl::display(), (EGLImageKHR) handle, EGL_WIDTH, &newWidth); - QMeeGoExtensions::eglQueryImageNOK(QEgl::display(), (EGLImageKHR) handle, EGL_HEIGHT, &newHeight); - - if (textureIsBound) { - // FIXME Remove this ugly hasAlphaChannel check when Qt lands the NoOpaqueCheck flag fix - // for QGLPixmapData. - fromTexture(newTextureId, newWidth, newHeight, true); - } else { - qWarning("Failed to create a texture from an egl image!"); - glDeleteTextures(1, &newTextureId); - } -} - void QMeeGoPixmapData::fromEGLSharedImage(Qt::HANDLE handle, const QImage &si) { if (si.isNull()) @@ -133,12 +108,10 @@ void QMeeGoPixmapData::fromEGLSharedImage(Qt::HANDLE handle, const QImage &si) glGenTextures(1, &newTextureId); glBindTexture(GL_TEXTURE_2D, newTextureId); - glFinish(); EGLImageKHR image = QEgl::eglCreateImageKHR(QEgl::display(), EGL_NO_CONTEXT, EGL_SHARED_IMAGE_NOK, (EGLClientBuffer)handle, preserved_image_attribs); if (image != EGL_NO_IMAGE_KHR) { - glFinish(); glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image); GLint err = glGetError(); if (err == GL_NO_ERROR) @@ -148,14 +121,12 @@ void QMeeGoPixmapData::fromEGLSharedImage(Qt::HANDLE handle, const QImage &si) QMeeGoExtensions::eglQueryImageNOK(QEgl::display(), image, EGL_HEIGHT, &newHeight); QEgl::eglDestroyImageKHR(QEgl::display(), image); - glFinish(); } if (textureIsBound) { - // FIXME Remove this ugly hasAlphaChannel check when Qt lands the NoOpaqueCheck flag fix - // for QGLPixmapData. fromTexture(newTextureId, newWidth, newHeight, (si.hasAlphaChannel() && const_cast<QImage &>(si).data_ptr()->checkForAlphaPixels())); + texture()->options &= ~QGLContext::InvertedYBindOption; softImage = si; QMeeGoPixmapData::registerSharedImage(handle, softImage); } else { @@ -170,22 +141,32 @@ Qt::HANDLE QMeeGoPixmapData::imageToEGLSharedImage(const QImage &image) QMeeGoExtensions::ensureInitialized(); - glFinish(); - QGLPixmapData pixmapData(QPixmapData::PixmapType); - pixmapData.fromImage(image, 0); - GLuint textureId = pixmapData.bind(); + GLuint textureId; + + glGenTextures(1, &textureId); + glBindTexture(GL_TEXTURE_2D, textureId); + if (image.hasAlphaChannel() && const_cast<QImage &>(image).data_ptr()->checkForAlphaPixels()) { + void *converted = convertARGB32_to_RGBA4444(image.bits(), image.width(), image.height(), image.bytesPerLine()); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image.width(), image.height(), 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, converted); + free(converted); + } else { + void *converted = convertRGB32_to_RGB565(image.bits(), image.width(), image.height(), image.bytesPerLine()); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, image.width(), image.height(), 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, converted); + free(converted); + } - glFinish(); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + + glBindTexture(GL_TEXTURE_2D, textureId); EGLImageKHR eglimage = QEgl::eglCreateImageKHR(QEgl::display(), QEglContext::currentContext(QEgl::OpenGL)->context(), EGL_GL_TEXTURE_2D_KHR, (EGLClientBuffer) textureId, preserved_image_attribs); - glFinish(); - + glDeleteTextures(1, &textureId); if (eglimage) { EGLNativeSharedImageTypeNOK handle = QMeeGoExtensions::eglCreateSharedImageNOK(QEgl::display(), eglimage, NULL); QEgl::eglDestroyImageKHR(QEgl::display(), eglimage); - glFinish(); return (Qt::HANDLE) handle; } else { qWarning("Failed to create shared image from pixmap/texture!"); @@ -195,6 +176,7 @@ Qt::HANDLE QMeeGoPixmapData::imageToEGLSharedImage(const QImage &image) void QMeeGoPixmapData::updateFromSoftImage() { + // FIXME That's broken with recent 16bit textures changes. m_dirty = true; m_source = softImage; ensureCreated(); @@ -234,3 +216,8 @@ void QMeeGoPixmapData::registerSharedImage(Qt::HANDLE handle, const QImage &si) qWarning("Inconsistency detected: overwriting entry in sharedImagesMap but handle/format different"); } } + +QPixmapData *QMeeGoPixmapData::createCompatiblePixmapData() const +{ + return new QMeeGoRasterPixmapData(pixelType()); +} diff --git a/src/plugins/graphicssystems/meego/qmeegopixmapdata.h b/src/plugins/graphicssystems/meego/qmeegopixmapdata.h index 8b1ae14..c66e719 100644 --- a/src/plugins/graphicssystems/meego/qmeegopixmapdata.h +++ b/src/plugins/graphicssystems/meego/qmeegopixmapdata.h @@ -55,8 +55,8 @@ class QMeeGoPixmapData : public QGLPixmapData public: QMeeGoPixmapData(); void fromTexture(GLuint textureId, int w, int h, bool alpha); + QPixmapData *createCompatiblePixmapData() const; - virtual void fromEGLImage(Qt::HANDLE handle); virtual void fromEGLSharedImage(Qt::HANDLE handle, const QImage &softImage); virtual void fromImage (const QImage &image, Qt::ImageConversionFlags flags); virtual QImage toImage() const; diff --git a/src/plugins/graphicssystems/meego/qmeegorasterpixmapdata.cpp b/src/plugins/graphicssystems/meego/qmeegorasterpixmapdata.cpp new file mode 100644 index 0000000..b6a3727 --- /dev/null +++ b/src/plugins/graphicssystems/meego/qmeegorasterpixmapdata.cpp @@ -0,0 +1,60 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qmeegorasterpixmapdata.h" + +/* Public */ + +QMeeGoRasterPixmapData::QMeeGoRasterPixmapData() : QRasterPixmapData(QPixmapData::PixmapType) +{ +} + +QMeeGoRasterPixmapData::QMeeGoRasterPixmapData(QPixmapData::PixelType t) : QRasterPixmapData(t) +{ +} + +void QMeeGoRasterPixmapData::copy(const QPixmapData *data, const QRect &rect) +{ + if (data->classId() == QPixmapData::OpenGLClass) + fromImage(data->toImage(rect).copy(), Qt::NoOpaqueDetection); + else + QRasterPixmapData::copy(data, rect); +} diff --git a/src/plugins/graphicssystems/meego/qmeegorasterpixmapdata.h b/src/plugins/graphicssystems/meego/qmeegorasterpixmapdata.h new file mode 100644 index 0000000..636b0e6 --- /dev/null +++ b/src/plugins/graphicssystems/meego/qmeegorasterpixmapdata.h @@ -0,0 +1,55 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef MRASTERPIXMAPDATA_H +#define MRASTERPIXMAPDATA_H + +#include <private/qpixmap_raster_p.h> + +class QMeeGoRasterPixmapData : public QRasterPixmapData +{ +public: + QMeeGoRasterPixmapData(); + QMeeGoRasterPixmapData(QPixmapData::PixelType t); + void copy(const QPixmapData *data, const QRect &rect); +}; + +#endif diff --git a/src/plugins/s60/feedback/feedback.pro b/src/plugins/s60/feedback/feedback.pro new file mode 100644 index 0000000..1069220 --- /dev/null +++ b/src/plugins/s60/feedback/feedback.pro @@ -0,0 +1,18 @@ +include(../../qpluginbase.pri) + +TARGET = qtactilefeedback$${QT_LIBINFIX} + +QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/s60/feedback + +INCLUDEPATH += $$APP_LAYER_SYSTEMINCLUDE + +contains(S60_VERSION, 5.0)|contains(S60_VERSION, symbian3) { + HEADERS += qtactileFeedback.h + SOURCES += qtactileFeedback_s60.cpp + + LIBS += -ltouchfeedback +} + +load(data_caging_paths) + +TARGET.UID3=0x200315B4 diff --git a/src/plugins/s60/feedback/qtactileFeedback.h b/src/plugins/s60/feedback/qtactileFeedback.h new file mode 100644 index 0000000..7c4cc29 --- /dev/null +++ b/src/plugins/s60/feedback/qtactileFeedback.h @@ -0,0 +1,54 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QEvent> +#include <QWidget> + +#include "private/qs60style_feedbackinterface_p.h" + +class QTactileFeedback : public TactileFeedbackInterface +{ + Q_OBJECT + Q_INTERFACES(TactileFeedbackInterface) + + public: + void touchFeedback(QEvent *event, const QWidget *widget); + }; diff --git a/src/plugins/s60/feedback/qtactileFeedback_s60.cpp b/src/plugins/s60/feedback/qtactileFeedback_s60.cpp new file mode 100644 index 0000000..c2f1d34 --- /dev/null +++ b/src/plugins/s60/feedback/qtactileFeedback_s60.cpp @@ -0,0 +1,83 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QApplication> +#include <QObject> +#include <QSlider> +#include <QScrollBar> + +#include <QtCore/qplugin.h> +#include "qtactileFeedback.h" + +#include <touchfeedback.h> + +void QTactileFeedback::touchFeedback(QEvent *event, const QWidget *widget) +{ + //Lets share the global instance for touch feedback (you are NOT allowed to try and delete it!). + MTouchFeedback* feedback = MTouchFeedback::Instance(); + + //If the widget itself is not handling focus, try to use focusProxy widget. + const QWidget *w = ((widget->focusPolicy() == Qt::NoFocus) && (widget->focusProxy())) ? widget->focusProxy() : widget; + + //Only give tactile feedback for enabled widgets that take focus. + if (feedback && w && w->isEnabled() && w->isWidgetType() && w->isVisible()) { + //Scrollbars are 'special' that they don't take focus (nor they have focusProxy), yet we'd like to have tactile feedback for them + if (w->focusPolicy() == Qt::NoFocus) + if (!qobject_cast<const QScrollBar *>(w)) + return; + + //Don't give tactile feedback for widgets that are outside topmost dialog. + QWidget *dialog = QApplication::activeModalWidget(); + if (dialog) { + QList<const QWidget *> allChildren = dialog->findChildren<const QWidget *>(); + if (!allChildren.contains(w)) + return; + } + + //Widget specific tactile feedback. + if (qobject_cast<const QSlider *>(w) || qobject_cast<const QScrollBar *>(w)) + feedback->InstantFeedback(ETouchFeedbackSensitive); + else + feedback->InstantFeedback(ETouchFeedbackBasic); + } +} + +Q_EXPORT_PLUGIN2("feedback", QTactileFeedback); diff --git a/src/plugins/s60/s60.pro b/src/plugins/s60/s60.pro index c999fff..ffcd170 100644 --- a/src/plugins/s60/s60.pro +++ b/src/plugins/s60/s60.pro @@ -6,6 +6,10 @@ symbian { SUBDIRS += 3_1 3_2 } + contains(S60_VERSION, 5.0)|contains(S60_VERSION, symbian3) { + SUBDIRS += feedback + } + # 5.0 is used also for Symbian3 and later SUBDIRS += 5_0 }
\ No newline at end of file |