#include <qqmlengine.h>
#include <private/qv8domerrors_p.h>
#include <QtCore/qnumeric.h>
+#include <private/qquickcanvas_p.h>
+#include <private/qquickwindowmanager_p.h>
+#include <QtGui/private/qguiapplication_p.h>
+#include <qpa/qplatformintegration.h>
#ifdef Q_OS_QNX
#include <ctype.h>
: QQuickCanvasContext(parent)
, m_buffer(new QQuickContext2DCommandBuffer)
, m_v8engine(0)
+ , m_windowManager(0)
+ , m_surface(0)
+ , m_glContext(0)
{
}
m_canvas = canvasItem;
m_renderTarget = canvasItem->renderTarget();
- // For the FBO target we only (currently) support Cooperative
- if (m_renderTarget == QQuickCanvasItem::FramebufferObject) {
- canvasItem->setRenderStrategy(QQuickCanvasItem::Cooperative);
- }
-
+ QQuickCanvas *canvas = canvasItem->canvas();
+ m_windowManager = QQuickCanvasPrivate::get(canvas)->windowManager;
m_renderStrategy = canvasItem->renderStrategy();
switch (m_renderTarget) {
m_texture = new QQuickContext2DImageTexture(m_renderStrategy == QQuickCanvasItem::Threaded);
break;
case QQuickCanvasItem::FramebufferObject:
+ {
m_texture = new QQuickContext2DFBOTexture;
+ // No BufferQueueingOpenGL, falls back to Cooperative mode
+ if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::BufferQueueingOpenGL))
+ m_renderStrategy = QQuickCanvasItem::Cooperative;
+ }
break;
}
m_texture->setCanvasSize(canvasItem->canvasSize().toSize());
m_texture->setSmooth(canvasItem->smooth());
+ QThread *renderThread = QThread::currentThread();
+ QThread *sceneGraphThread = canvas->openglContext() ? canvas->openglContext()->thread() : 0;
+
+ if (m_renderStrategy == QQuickCanvasItem::Threaded)
+ renderThread = QQuickContext2DRenderThread::instance(qmlEngine(canvasItem));
+ else if (m_renderStrategy == QQuickCanvasItem::Cooperative)
+ renderThread = sceneGraphThread;
+
+ if (m_renderTarget == QQuickCanvasItem::FramebufferObject && renderThread != sceneGraphThread) {
+ QOpenGLContext *cc = QQuickCanvasPrivate::get(canvas)->context->glContext();
+ m_surface = canvas;
+ m_glContext = new QOpenGLContext;
+ m_glContext->setFormat(cc->format());
+ m_glContext->setShareContext(cc);
+ if (renderThread != QThread::currentThread())
+ m_glContext->moveToThread(renderThread);
+ }
+
connect(m_texture, SIGNAL(textureChanged()), SIGNAL(textureChanged()));
reset();
class QQuickContext2DTexture;
class QQuickPixmap;
class QSGTexture;
-
+class QQuickWindowManager;
+class QSurface;
+class QOpenGLContext;
class QQuickContext2D : public QQuickCanvasContext
{
QPainterPath createTextGlyphs(qreal x, qreal y, const QString& text);
QImage createImage(const QUrl& url);
+ QOpenGLContext *glContext() { return m_glContext; }
+ QSurface *surface() { return m_surface; }
+
State state;
QStack<QQuickContext2D::State> m_stateStack;
QQuickCanvasItem* m_canvas;
v8::Local<v8::Value> m_strokeStyle;
v8::Handle<v8::Value> m_v8path;
QV8Engine *m_v8engine;
+ QQuickWindowManager *m_windowManager;
+ QSurface *m_surface;
+ QOpenGLContext *m_glContext;
v8::Persistent<v8::Object> m_v8value;
QQuickContext2DTexture *m_texture;
QQuickCanvasItem::RenderTarget m_renderTarget;
return v;
}
+struct GLAcquireContext {
+ GLAcquireContext(QOpenGLContext *c, QSurface *s):ctx(c) {
+ if (ctx) {
+ Q_ASSERT(s);
+ if (!ctx->isValid())
+ ctx->create();
+
+ if (!ctx->isValid())
+ qWarning() << "Unable to create GL context";
+ else if (!ctx->makeCurrent(s))
+ qWarning() << "Can't make current GL context";
+ }
+ }
+ ~GLAcquireContext() {
+ if (ctx)
+ ctx->doneCurrent();
+ }
+ QOpenGLContext *ctx;
+};
Q_GLOBAL_STATIC(QThread, globalCanvasThreadRenderInstance)
if (canvasDestroyed())
return;
+ GLAcquireContext currentContext(m_context->glContext(), m_context->surface());
+
if (m_threadRendering && QThread::currentThread() != globalCanvasThreadRenderInstance()) {
Q_ASSERT(thread() == globalCanvasThreadRenderInstance());
QMetaObject::invokeMethod(this, "paint", Qt::QueuedConnection);