QQuickCanvas renames
[profile/ivi/qtdeclarative.git] / src / quick / scenegraph / qsgshareddistancefieldglyphcache.cpp
index dd9db4e..dcbff84 100644 (file)
 
 #include <QtCore/qhash.h>
 #include <QtCore/qthread.h>
-#include <QtGui/qplatformsharedgraphicscache_qpa.h>
+#include <QtCore/qcoreapplication.h>
 
-#include <QtQuick/qquickcanvas.h>
+#include <qpa/qplatformsharedgraphicscache.h>
 
-#include <QtOpenGL/qglframebufferobject.h>
+#include <QtQuick/qquickwindow.h>
 
 // #define QSGSHAREDDISTANCEFIELDGLYPHCACHE_DEBUG
 
-Q_DECLARE_METATYPE(QVector<quint32>)
-Q_DECLARE_METATYPE(QVector<QImage>)
-
 QT_BEGIN_NAMESPACE
 
+namespace {
+
+    class QSGInvokeEvent: public QEvent
+    {
+    public:
+        QSGInvokeEvent(QPlatformSharedGraphicsCache *cache,
+                       const QByteArray &cacheId = QByteArray(),
+                       const QVector<quint32> &glyphIds = QVector<quint32>(),
+                       bool inSceneGraphUpdate = false)
+            : QEvent(User)
+            , m_cache(cache)
+            , m_cacheId(cacheId)
+            , m_glyphIds(glyphIds)
+            , m_inSceneGraphUpdate(inSceneGraphUpdate)
+        {}
+
+        bool inSceneGraphUpdate() const { return m_inSceneGraphUpdate; }
+        QPlatformSharedGraphicsCache *cache() const { return m_cache; }
+
+        virtual void invoke() = 0;
+    protected:
+        QPlatformSharedGraphicsCache *m_cache;
+        QByteArray m_cacheId;
+        QVector<quint32> m_glyphIds;
+        bool m_inSceneGraphUpdate;
+    };
+
+    class QSGReleaseItemsEvent: public QSGInvokeEvent
+    {
+    public:
+        QSGReleaseItemsEvent(QPlatformSharedGraphicsCache *cache,
+                             const QByteArray &cacheId,
+                             const QVector<quint32> &glyphIds,
+                             bool inSceneGraphUpdate)
+            : QSGInvokeEvent(cache, cacheId, glyphIds, inSceneGraphUpdate)
+        {
+        }
+
+        void invoke()
+        {
+            m_cache->releaseItems(m_cacheId, m_glyphIds);
+        }
+    };
+
+    class QSGRequestItemsEvent: public QSGInvokeEvent
+    {
+    public:
+        QSGRequestItemsEvent(QPlatformSharedGraphicsCache *cache,
+                             const QByteArray &cacheId,
+                             const QVector<quint32> &glyphIds,
+                             bool inSceneGraphUpdate)
+            : QSGInvokeEvent(cache, cacheId, glyphIds, inSceneGraphUpdate)
+        {
+        }
+
+        void invoke()
+        {
+            m_cache->requestItems(m_cacheId, m_glyphIds);
+        }
+    };
+
+    class QSGInsertItemsEvent: public QSGInvokeEvent
+    {
+    public:
+        QSGInsertItemsEvent(QPlatformSharedGraphicsCache *cache,
+                            const QByteArray &cacheId,
+                            const QVector<quint32> &glyphIds,
+                            const QVector<QImage> &images,
+                            bool inSceneGraphUpdate)
+            : QSGInvokeEvent(cache, cacheId, glyphIds, inSceneGraphUpdate)
+            , m_images(images)
+        {
+        }
+
+        void invoke()
+        {
+            m_cache->insertItems(m_cacheId, m_glyphIds, m_images);
+        }
+
+    private:
+        QVector<QImage> m_images;
+    };
+
+    class QSGEndRequestBatchEvent: public QSGInvokeEvent
+    {
+    public:
+        QSGEndRequestBatchEvent(QPlatformSharedGraphicsCache *cache)
+            : QSGInvokeEvent(cache)
+        {
+        }
+
+        void invoke()
+        {
+            if (m_cache->requestBatchStarted())
+                m_cache->endRequestBatch();
+        }
+    };
+
+    class QSGMainThreadInvoker: public QObject
+    {
+    public:
+        bool event(QEvent *e)
+        {
+            if (e->type() == QEvent::User) {
+                Q_ASSERT(QThread::currentThread() == QCoreApplication::instance()->thread());
+
+                QSGInvokeEvent *invokeEvent = static_cast<QSGInvokeEvent *>(e);
+                if (invokeEvent->inSceneGraphUpdate()) {
+                    QPlatformSharedGraphicsCache *cache = invokeEvent->cache();
+                    if (!cache->requestBatchStarted())
+                        cache->beginRequestBatch();
+                }
+
+                static_cast<QSGInvokeEvent *>(e)->invoke();
+                return true;
+            }
+            return QObject::event(e);
+        }
+
+        static QSGMainThreadInvoker *instance()
+        {
+            if (m_invoker == 0) {
+                m_invoker = new QSGMainThreadInvoker;
+                m_invoker->moveToThread(QCoreApplication::instance()->thread());
+            }
+
+            return m_invoker;
+        }
+
+    private:
+        static QSGMainThreadInvoker *m_invoker;
+    };
+
+    QSGMainThreadInvoker* QSGMainThreadInvoker::m_invoker = 0;
+}
+
 QSGSharedDistanceFieldGlyphCache::QSGSharedDistanceFieldGlyphCache(const QByteArray &cacheId,
                                                                    QPlatformSharedGraphicsCache *sharedGraphicsCache,
                                                                    QSGDistanceFieldGlyphCacheManager *man,
@@ -71,6 +204,8 @@ QSGSharedDistanceFieldGlyphCache::QSGSharedDistanceFieldGlyphCache(const QByteAr
     : QSGDistanceFieldGlyphCache(man, c, font)
     , m_cacheId(cacheId)
     , m_sharedGraphicsCache(sharedGraphicsCache)
+    , m_isInSceneGraphUpdate(false)
+    , m_hasPostedEvents(false)
 {
 #if defined(QSGSHAREDDISTANCEFIELDGLYPHCACHE_DEBUG)
     qDebug("QSGSharedDistanceFieldGlyphCache with id %s created in thread %p",
@@ -80,9 +215,6 @@ QSGSharedDistanceFieldGlyphCache::QSGSharedDistanceFieldGlyphCache(const QByteAr
     Q_ASSERT(sizeof(glyph_t) == sizeof(quint32));
     Q_ASSERT(sharedGraphicsCache != 0);
 
-    qRegisterMetaType<QVector<quint32> >();
-    qRegisterMetaType<QVector<QImage> >();
-
     connect(sharedGraphicsCache, SIGNAL(itemsMissing(QByteArray,QVector<quint32>)),
             this, SLOT(reportItemsMissing(QByteArray,QVector<quint32>)),
             Qt::DirectConnection);
@@ -95,6 +227,14 @@ QSGSharedDistanceFieldGlyphCache::QSGSharedDistanceFieldGlyphCache(const QByteAr
     connect(sharedGraphicsCache, SIGNAL(itemsInvalidated(QByteArray,QVector<quint32>)),
             this, SLOT(reportItemsInvalidated(QByteArray,QVector<quint32>)),
             Qt::DirectConnection);
+
+    QQuickWindow *window = static_cast<QQuickWindow *>(c->surface());
+    Q_ASSERT(window != 0);
+
+    connect(window, SIGNAL(beforeSynchronizing()), this, SLOT(sceneGraphUpdateStarted()),
+            Qt::DirectConnection);
+    connect(window, SIGNAL(beforeRendering()), this, SLOT(sceneGraphUpdateDone()),
+            Qt::DirectConnection);
 }
 
 QSGSharedDistanceFieldGlyphCache::~QSGSharedDistanceFieldGlyphCache()
@@ -137,15 +277,22 @@ void QSGSharedDistanceFieldGlyphCache::requestGlyphs(const QSet<glyph_t> &glyphs
         glyphsVector.append(*it);
     }
 
-    // Invoke method on queued connection to make sure it's called asynchronously on the
-    // correct thread (requestGlyphs() is called from the rendering thread.)
-    QMetaObject::invokeMethod(m_sharedGraphicsCache, "requestItems", Qt::QueuedConnection,
-                              Q_ARG(QByteArray, m_cacheId),
-                              Q_ARG(QVector<quint32>, glyphsVector));
+    m_hasPostedEvents = true;
+    QSGMainThreadInvoker *invoker = QSGMainThreadInvoker::instance();
+    QCoreApplication::postEvent(invoker, new QSGRequestItemsEvent(m_sharedGraphicsCache,
+                                                                  m_cacheId,
+                                                                  glyphsVector,
+                                                                  m_isInSceneGraphUpdate));
 }
 
 void QSGSharedDistanceFieldGlyphCache::waitForGlyphs()
 {
+    Q_ASSERT(!m_isInSceneGraphUpdate);
+    if (m_isInSceneGraphUpdate) {
+        qWarning("QSGSharedDistanceFieldGlyphCache::waitForGlyphs: Called from inside "
+                 "scenegraph update. Will freeze.");
+    }
+
     {
         QMutexLocker locker(&m_pendingGlyphsMutex);
         while (!m_requestedGlyphsThatHaveNotBeenReturned.isEmpty())
@@ -175,10 +322,13 @@ void QSGSharedDistanceFieldGlyphCache::storeGlyphs(const QHash<glyph_t, QImage>
             ++it; ++i;
         }
 
-        QMetaObject::invokeMethod(m_sharedGraphicsCache, "insertItems", Qt::QueuedConnection,
-                                  Q_ARG(QByteArray, m_cacheId),
-                                  Q_ARG(QVector<quint32>, glyphIds),
-                                  Q_ARG(QVector<QImage>, images));
+        m_hasPostedEvents = true;
+        QSGMainThreadInvoker *invoker = QSGMainThreadInvoker::instance();
+        QCoreApplication::postEvent(invoker, new QSGInsertItemsEvent(m_sharedGraphicsCache,
+                                                                     m_cacheId,
+                                                                     glyphIds,
+                                                                     images,
+                                                                     m_isInSceneGraphUpdate));
     }
 
     processPendingGlyphs();
@@ -227,9 +377,12 @@ void QSGSharedDistanceFieldGlyphCache::releaseGlyphs(const QSet<glyph_t> &glyphs
         glyphsVector.append(*glyphsIt);
     }
 
-    QMetaObject::invokeMethod(m_sharedGraphicsCache, "releaseItems", Qt::QueuedConnection,
-                              Q_ARG(QByteArray, m_cacheId),
-                              Q_ARG(QVector<quint32>, glyphsVector));
+    m_hasPostedEvents = true;
+    QSGMainThreadInvoker *mainThreadInvoker = QSGMainThreadInvoker::instance();
+    QCoreApplication::postEvent(mainThreadInvoker, new QSGReleaseItemsEvent(m_sharedGraphicsCache,
+                                                                            m_cacheId,
+                                                                            glyphsVector,
+                                                                            m_isInSceneGraphUpdate));
 }
 
 void QSGSharedDistanceFieldGlyphCache::registerOwnerElement(QQuickItem *ownerElement)
@@ -403,7 +556,7 @@ void QSGSharedDistanceFieldGlyphCache::saveTexture(GLuint textureId, int width,
     for (int i=0; i<width*height; ++i)
         dest[i] = qRgba(0xff, 0xff, 0xff, data[i]);
 
-    QByteArray fileName = m_cacheId + " " + QByteArray::number(textureId);
+    QByteArray fileName = m_cacheId + ' ' + QByteArray::number(textureId);
     fileName = fileName.replace('/', '_').replace(' ', '_') + ".png";
     image.save(QString::fromLocal8Bit(fileName));
 
@@ -662,4 +815,21 @@ void QSGSharedDistanceFieldGlyphCache::reportItemsMissing(const QByteArray &cach
     emit glyphsPending();
 }
 
+void QSGSharedDistanceFieldGlyphCache::sceneGraphUpdateStarted()
+{
+    m_isInSceneGraphUpdate = true;
+    m_hasPostedEvents = false;
+}
+
+void QSGSharedDistanceFieldGlyphCache::sceneGraphUpdateDone()
+{
+    m_isInSceneGraphUpdate = false;
+
+    if (m_hasPostedEvents) {
+        QSGMainThreadInvoker *invoker = QSGMainThreadInvoker::instance();
+        QCoreApplication::postEvent(invoker, new QSGEndRequestBatchEvent(m_sharedGraphicsCache));
+        m_hasPostedEvents = false;
+    }
+}
+
 QT_END_NAMESPACE