aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGunnar Sletta <gunnar.sletta@nokia.com>2012-01-26 11:17:37 +0100
committerQt by Nokia <qt-info@nokia.com>2012-02-02 17:27:12 +0100
commit20d641a4eb1a3ffe1cff41491b64b6b857982847 (patch)
tree31d1fbcdb81db90bd47de839ba3b070a499e7c59
parentfd39d7eeec32fb29541decc11115608f9b759c86 (diff)
Started implementation of offscreen canvas FBO rendering API
Change-Id: I15b1799982d20d16c9c5e08eee7095cf087b49e1 Reviewed-by: Kim M. Kalland <kim.kalland@nokia.com>
-rw-r--r--src/quick/items/qquickcanvas.cpp25
-rw-r--r--src/quick/items/qquickcanvas_p.h5
-rw-r--r--src/quick/items/qquickwindowmanager.cpp55
3 files changed, 76 insertions, 9 deletions
diff --git a/src/quick/items/qquickcanvas.cpp b/src/quick/items/qquickcanvas.cpp
index ac7928f286..72300f9ce5 100644
--- a/src/quick/items/qquickcanvas.cpp
+++ b/src/quick/items/qquickcanvas.cpp
@@ -204,6 +204,30 @@ void QQuickCanvasPrivate::polishItems()
updateFocusItemTransform();
}
+/**
+ * This parameter enables that this canvas can be rendered without
+ * being shown on screen. This feature is very limited in what it supports.
+ *
+ * There needs to be another window actually showing that we can make current
+ * to get a surface to make current AND for this feature to be useful
+ * one needs to hook into beforeRender() and set the render tareget.
+ *
+ */
+void QQuickCanvasPrivate::setRenderWithoutShowing(bool render)
+{
+ if (render == renderWithoutShowing)
+ return;
+
+ Q_Q(QQuickCanvas);
+ renderWithoutShowing = render;
+
+ if (render)
+ windowManager->show(q);
+ else
+ windowManager->hide(q);
+}
+
+
void forceUpdate(QQuickItem *item)
{
if (item->flags() & QQuickItem::ItemHasContents)
@@ -253,6 +277,7 @@ QQuickCanvasPrivate::QQuickCanvasPrivate()
: rootItem(0)
, activeFocusItem(0)
, mouseGrabberItem(0)
+ , renderWithoutShowing(false)
, dirtyItemList(0)
, context(0)
, renderer(0)
diff --git a/src/quick/items/qquickcanvas_p.h b/src/quick/items/qquickcanvas_p.h
index d5021d880a..45b87c67b7 100644
--- a/src/quick/items/qquickcanvas_p.h
+++ b/src/quick/items/qquickcanvas_p.h
@@ -93,7 +93,7 @@ class QTouchEvent;
class QQuickCanvasRenderLoop;
class QQuickCanvasIncubationController;
-class QQuickCanvasPrivate : public QWindowPrivate
+class Q_QUICK_EXPORT QQuickCanvasPrivate : public QWindowPrivate
{
public:
Q_DECLARE_PUBLIC(QQuickCanvas)
@@ -152,6 +152,9 @@ public:
void syncSceneGraph();
void renderSceneGraph(const QSize &size);
+ bool renderWithoutShowing;
+ void setRenderWithoutShowing(bool enabled);
+
QQuickItem::UpdatePaintNodeData updatePaintNodeData;
QQuickItem *dirtyItemList;
diff --git a/src/quick/items/qquickwindowmanager.cpp b/src/quick/items/qquickwindowmanager.cpp
index b5dd2da746..d54be90385 100644
--- a/src/quick/items/qquickwindowmanager.cpp
+++ b/src/quick/items/qquickwindowmanager.cpp
@@ -208,6 +208,16 @@ public:
void run();
+ QQuickCanvas *masterCanvas() {
+ QQuickCanvas *win = 0;
+ for (QHash<QQuickCanvas *, CanvasData *>::const_iterator it = m_rendered_windows.constBegin();
+ it != m_rendered_windows.constEnd() && !win; ++it) {
+ if (it.value()->isVisible)
+ win = it.key();
+ }
+ return win;
+ }
+
public slots:
void animationStarted();
void animationStopped();
@@ -249,6 +259,7 @@ private:
QSize viewportSize;
uint sizeWasChanged : 1;
+ uint isVisible : 1;
};
QHash<QQuickCanvas *, CanvasData *> m_rendered_windows;
@@ -276,6 +287,7 @@ public:
void canvasDestroyed(QQuickCanvas *canvas);
+ void initializeGL();
void renderCanvas(QQuickCanvas *canvas);
void paint(QQuickCanvas *canvas);
QImage grab(QQuickCanvas *canvas);
@@ -329,7 +341,10 @@ QQuickWindowManager *QQuickWindowManager::instance()
void QQuickRenderThreadSingleContextWindowManager::initialize()
{
Q_ASSERT(m_rendered_windows.size());
- QQuickCanvas *win = m_rendered_windows.constBegin().key();
+
+ QQuickCanvas *win = masterCanvas();
+ if (!win)
+ return;
gl = new QOpenGLContext();
// Pick up the surface format from one of them
@@ -378,6 +393,7 @@ void QQuickRenderThreadSingleContextWindowManager::handleAddedWindow(QQuickCanva
CanvasData *data = new CanvasData;
data->sizeWasChanged = false;
data->windowSize = canvas->size();
+ data->isVisible = canvas->visible();
m_rendered_windows[canvas] = data;
isExternalUpdatePending = true;
@@ -489,7 +505,7 @@ void QQuickRenderThreadSingleContextWindowManager::canvasVisibilityChanged()
CanvasTracker &t = const_cast<CanvasTracker &>(m_tracked_windows.at(i));
QQuickCanvas *win = t.canvas;
- Q_ASSERT(win->visible() || t.toBeRemoved);
+ Q_ASSERT(win->visible() || QQuickCanvasPrivate::get(win)->renderWithoutShowing || t.toBeRemoved);
bool canvasVisible = win->width() > 0 && win->height() > 0;
anyoneShowing |= (canvasVisible && !t.toBeRemoved);
@@ -541,6 +557,9 @@ void QQuickRenderThreadSingleContextWindowManager::run()
wake();
unlock();
+ if (!gl)
+ return;
+
while (!shouldExit) {
lock();
@@ -591,7 +610,10 @@ void QQuickRenderThreadSingleContextWindowManager::run()
Q_ASSERT(canvasData->windowSize.width() > 0 && canvasData->windowSize.height() > 0);
- gl->makeCurrent(canvas);
+ if (!canvasData->isVisible)
+ gl->makeCurrent(masterCanvas());
+ else
+ gl->makeCurrent(canvas);
if (canvasData->viewportSize != canvasData->windowSize) {
#ifdef THREAD_DEBUG
@@ -660,7 +682,9 @@ void QQuickRenderThreadSingleContextWindowManager::run()
printf(" RenderThread: --- wait for swap...\n");
#endif
- gl->swapBuffers(canvas);
+ if (canvasData->isVisible)
+ gl->swapBuffers(canvas);
+
canvasPrivate->fireFrameSwapped();
#ifdef THREAD_DEBUG
printf(" RenderThread: --- swap complete...\n");
@@ -1141,15 +1165,30 @@ void QQuickTrivialWindowManager::renderCanvas(QQuickCanvas *canvas)
CanvasData &data = const_cast<CanvasData &>(m_windows[canvas]);
+ QQuickCanvas *masterCanvas = 0;
+ if (!canvas->visible()) {
+ // Find a "proper surface" to bind...
+ for (QHash<QQuickCanvas *, CanvasData>::const_iterator it = m_windows.constBegin();
+ it != m_windows.constEnd() && !masterCanvas; ++it) {
+ if (it.key()->visible())
+ masterCanvas = it.key();
+ }
+ } else {
+ masterCanvas = canvas;
+ }
+
+ if (!masterCanvas)
+ return;
+
if (!gl) {
gl = new QOpenGLContext();
- gl->setFormat(canvas->requestedFormat());
+ gl->setFormat(masterCanvas->requestedFormat());
gl->create();
- if (!gl->makeCurrent(canvas))
+ if (!gl->makeCurrent(masterCanvas))
qWarning("QQuickCanvas: makeCurrent() failed...");
sg->initialize(gl);
} else {
- gl->makeCurrent(canvas);
+ gl->makeCurrent(masterCanvas);
}
bool alsoSwap = data.updatePending;
@@ -1165,7 +1204,7 @@ void QQuickTrivialWindowManager::renderCanvas(QQuickCanvas *canvas)
data.grabOnly = false;
}
- if (alsoSwap) {
+ if (alsoSwap && canvas->visible()) {
gl->swapBuffers(canvas);
cd->fireFrameSwapped();
}