aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLaszlo Agocs <laszlo.agocs@theqtcompany.com>2015-04-17 10:53:25 +0200
committerLaszlo Agocs <laszlo.agocs@theqtcompany.com>2015-04-17 09:43:36 +0000
commit5051c63b3b818f5fb0ed9f92e74b916ea9d4e723 (patch)
treec44cd5f423d8e6a8217e7f7557ed9cd79c136bf6 /src
parent6d073d4e070790d4e9ef707a9deef975e9f70695 (diff)
Long live QtQuickCL!
Change-Id: I16954f50c631441189dd450980da2c3266a68c71 Reviewed-by: Andy Nichols <andy.nichols@theqtcompany.com>
Diffstat (limited to 'src')
-rw-r--r--src/quickcl/doc/qtquickcl.qdocconf65
-rw-r--r--src/quickcl/qquickclcontext.cpp199
-rw-r--r--src/quickcl/qquickclcontext_p.h67
-rw-r--r--src/quickcl/qquickclimagerunnable.cpp340
-rw-r--r--src/quickcl/qquickclimagerunnable.h82
-rw-r--r--src/quickcl/qquickclitem.cpp385
-rw-r--r--src/quickcl/qquickclitem.h84
-rw-r--r--src/quickcl/qquickclrunnable.h54
-rw-r--r--src/quickcl/qtquickclglobal.h65
-rw-r--r--src/quickcl/quickcl.pro24
-rw-r--r--src/src.pro3
11 files changed, 1368 insertions, 0 deletions
diff --git a/src/quickcl/doc/qtquickcl.qdocconf b/src/quickcl/doc/qtquickcl.qdocconf
new file mode 100644
index 0000000..583111c
--- /dev/null
+++ b/src/quickcl/doc/qtquickcl.qdocconf
@@ -0,0 +1,65 @@
+include($QT_INSTALL_DOCS/global/macros.qdocconf)
+include($QT_INSTALL_DOCS/global/qt-cpp-defines.qdocconf)
+include($QT_INSTALL_DOCS/global/compat.qdocconf)
+include($QT_INSTALL_DOCS/global/fileextensions.qdocconf)
+include($QT_INSTALL_DOCS/global/qt-html-templates-offline.qdocconf)
+
+project = QtQuickCL
+description = Qt Quick CL Reference Documentation
+url = http://doc.qt.io/QtQuickCL/
+version = 1.0
+
+qhp.projects = QtQuickCL
+
+qhp.QtQuickCL.file = qtquickcl.qhp
+qhp.QtQuickCL.namespace = com.qt.quickcl.1.0
+qhp.QtQuickCL.virtualFolder = qtquickcl
+qhp.QtQuickCL.indexTitle = Qt Quick CL
+qhp.QtQuickCL.indexRoot =
+qhp.QtQuickCL.filterAttributes = qtquickcl 1.0 qtrefdoc
+qhp.QtQuickCL.customFilters.Qt.name = QtQuickCL 1.0
+qhp.QtQuickCL.customFilters.Qt.filterAttributes = qtquickcl 1.0
+
+qhp.QtQuickCL.subprojects = qmltypes classes examples
+qhp.QtQuickCL.subprojects.qmltypes.title = QML Types
+qhp.QtQuickCL.subprojects.qmltypes.indexTitle = Qt Quick CL QML Types
+qhp.QtQuickCL.subprojects.qmltypes.selectors = fake:qmlclass
+qhp.QtQuickCL.subprojects.qmltypes.sortPages = true
+qhp.QtQuickCL.subprojects.classes.title = C++ Classes
+qhp.QtQuickCL.subprojects.classes.indexTitle = Qt Quick CL C++ Classes
+qhp.QtQuickCL.subprojects.classes.selectors = class fake:headerfile
+qhp.QtQuickCL.subprojects.classes.sortPages = true
+qhp.QtQuickCL.subprojects.examples.title = Examples
+qhp.QtQuickCL.subprojects.examples.indexTitle = Qt Quick CL Examples
+qhp.QtQuickCL.subprojects.examples.selectors = fake:example
+
+HTML.footer = \
+ "<div class=\"footer\">\n" \
+ " <p>\n" \
+ " <acronym title=\"Copyright\">&copy;</acronym> 2014 Digia. Qt and Qt logos are\n" \
+ " trademarks of of Digia Corporation in Finland and/or other countries worldwide.\n" \
+ " </p>\n" \
+ " All other trademarks are property of their respective owners.\n" \
+ " <br />\n" \
+ " <p>\n" \
+ " Licensees holding valid Qt Enterprise licenses may use this document in accordance\n" \
+ " with the Qt Enterprise License Agreement provided with the Software or,\n" \
+ " alternatively, in accordance with the terms contained in a written agreement\n" \
+ " between you and Digia.\n" \
+ " </p>\n" \
+ "</div>\n"
+
+indexes += $QT_INSTALL_DOCS/qtqml/qtqml.index \
+ $QT_INSTALL_DOCS/qtquick/qtquick.index \
+ $QT_INSTALL_DOCS/qtdoc/qtdoc.index \
+ $QT_INSTALL_DOCS/qtquickcontrols/qtquickcontrols.index
+
+headerdirs += ../
+sourcedirs += ../
+exampledirs += ../../../examples/
+imagedirs += images
+
+navigation.landingpage = "Qt Quick CL"
+navigation.qmltypespage = "Qt Quick CL QML Types"
+navigation.cppclassespage = "Qt Quick CL C++ Classes"
+buildversion = "Qt Quick CL 1.0"
diff --git a/src/quickcl/qquickclcontext.cpp b/src/quickcl/qquickclcontext.cpp
new file mode 100644
index 0000000..4c07593
--- /dev/null
+++ b/src/quickcl/qquickclcontext.cpp
@@ -0,0 +1,199 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick CL module
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qquickclcontext_p.h"
+
+#include <QtGui/QOpenGLContext>
+#include <QtGui/QOpenGLFunctions>
+#include <QtCore/QLoggingCategory>
+#include <qpa/qplatformnativeinterface.h>
+
+QT_BEGIN_NAMESPACE
+
+Q_LOGGING_CATEGORY(logCL, "qt.quickcl")
+
+QQuickCLContext::QQuickCLContext()
+ : m_platform(0),
+ m_device(0),
+ m_context(0)
+{
+}
+
+QQuickCLContext::~QQuickCLContext()
+{
+ destroy();
+}
+
+bool QQuickCLContext::create()
+{
+ destroy();
+ qCDebug(logCL, "Creating new OpenCL context");
+
+ QOpenGLContext *ctx = QOpenGLContext::currentContext();
+ if (!ctx) {
+ qWarning("Attempted CL-GL interop without a current OpenGL context");
+ return false;
+ }
+ QOpenGLFunctions *f = ctx->functions();
+
+ cl_uint n;
+ cl_int err = clGetPlatformIDs(0, 0, &n);
+ if (err != CL_SUCCESS) {
+ qWarning("Failed to get platform ID count (error %d)", err);
+ if (err == -1001) {
+ qWarning("Could not find OpenCL implementation. ICD missing?"
+#ifdef Q_OS_LINUX
+ " Check /etc/OpenCL/vendors."
+#endif
+ );
+ }
+ return false;
+ }
+ if (n == 0) {
+ qWarning("No OpenCL platform found");
+ return false;
+ }
+ QVector<cl_platform_id> platformIds;
+ platformIds.resize(n);
+ if (clGetPlatformIDs(n, platformIds.data(), 0) != CL_SUCCESS) {
+ qWarning("Failed to get platform IDs");
+ return false;
+ }
+ m_platform = platformIds[0];
+ const char *vendor = (const char *) f->glGetString(GL_VENDOR);
+ qCDebug(logCL, "GL_VENDOR: %s", vendor);
+ const bool isNV = vendor && strstr(vendor, "NVIDIA");
+ const bool isIntel = vendor && strstr(vendor, "Intel");
+ const bool isAMD = vendor && strstr(vendor, "ATI");
+ qCDebug(logCL, "Found %u OpenCL platforms:", n);
+ for (cl_uint i = 0; i < n; ++i) {
+ QByteArray name;
+ name.resize(1024);
+ clGetPlatformInfo(platformIds[i], CL_PLATFORM_NAME, name.size(), name.data(), 0);
+ qCDebug(logCL, "Platform %p: %s", platformIds[i], name.constData());
+ if (isNV && name.contains(QByteArrayLiteral("NVIDIA")))
+ m_platform = platformIds[i];
+ else if (isIntel && name.contains(QByteArrayLiteral("Intel")))
+ m_platform = platformIds[i];
+ else if (isAMD && name.contains(QByteArrayLiteral("AMD")))
+ m_platform = platformIds[i];
+ }
+ qCDebug(logCL, "Using platform %p", m_platform);
+
+#if defined (Q_OS_OSX)
+ cl_context_properties contextProps[] = { CL_CONTEXT_PROPERTY_USE_CGL_SHAREGROUP_APPLE,
+ (cl_context_properties) CGLGetShareGroup(CGLGetCurrentContext()),
+ 0 };
+#elif defined(Q_OS_WIN)
+ if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGLES) {
+ // We don't do D3D-CL interop.
+ qWarning("ANGLE is not supported");
+ return false;
+ }
+ cl_context_properties contextProps[] = { CL_CONTEXT_PLATFORM, (cl_context_properties) m_platform,
+ CL_GL_CONTEXT_KHR, (cl_context_properties) wglGetCurrentContext(),
+ CL_WGL_HDC_KHR, (cl_context_properties) wglGetCurrentDC(),
+ 0 };
+#elif defined(Q_OS_LINUX)
+ cl_context_properties contextProps[] = { CL_CONTEXT_PLATFORM, (cl_context_properties) m_platform,
+ CL_GL_CONTEXT_KHR, 0,
+ 0, 0,
+ 0 };
+ QPlatformNativeInterface *nativeIf = qGuiApp->platformNativeInterface();
+ void *dpy = nativeIf->nativeResourceForIntegration(QByteArrayLiteral("egldisplay")); // EGLDisplay
+ if (dpy) {
+ void *nativeContext = nativeIf->nativeResourceForContext("eglcontext", ctx);
+ if (!nativeContext)
+ qWarning("Failed to get the underlying EGL context from the current QOpenGLContext");
+ contextProps[3] = (cl_context_properties) nativeContext;
+ contextProps[4] = CL_EGL_DISPLAY_KHR;
+ contextProps[5] = (cl_context_properties) dpy;
+ } else {
+ dpy = nativeIf->nativeResourceForIntegration(QByteArrayLiteral("display")); // Display *
+ void *nativeContext = nativeIf->nativeResourceForContext("glxcontext", ctx);
+ if (!nativeContext)
+ qWarning("Failed to get the underlying GLX context from the current QOpenGLContext");
+ contextProps[3] = (cl_context_properties) nativeContext;
+ contextProps[4] = CL_GLX_DISPLAY_KHR;
+ contextProps[5] = (cl_context_properties) dpy;
+ }
+#endif
+
+ m_context = clCreateContextFromType(contextProps, CL_DEVICE_TYPE_GPU, 0, 0, &err);
+ if (!m_context) {
+ qWarning("Failed to create OpenCL context: %d", err);
+ return false;
+ }
+ qCDebug(logCL, "Using context %p", m_context);
+
+#if defined(Q_OS_OSX)
+ err = clGetGLContextInfoAPPLE(m_context, CGLGetCurrentContext(),
+ CL_CGL_DEVICE_FOR_CURRENT_VIRTUAL_SCREEN_APPLE,
+ sizeof(cl_device_id), &m_device, 0);
+ if (err != CL_SUCCESS) {
+ qWarning("Failed to get OpenCL device for current screen: %d", err);
+ destroy();
+ return false;
+ }
+#else
+ clGetGLContextInfoKHR_fn getGLContextInfo = (clGetGLContextInfoKHR_fn) clGetExtensionFunctionAddress("clGetGLContextInfoKHR");
+ if (!getGLContextInfo || getGLContextInfo(contextProps, CL_CURRENT_DEVICE_FOR_GL_CONTEXT_KHR,
+ sizeof(cl_device_id), &m_device, 0) != CL_SUCCESS) {
+ err = clGetDeviceIDs(m_platform, CL_DEVICE_TYPE_GPU, 1, &m_device, 0);
+ if (err != CL_SUCCESS) {
+ qWarning("Failed to get OpenCL device: %d", err);
+ destroy();
+ return false;
+ }
+ }
+#endif
+ qCDebug(logCL, "Using device %p", m_device);
+
+ return true;
+}
+
+void QQuickCLContext::destroy()
+{
+ if (m_context) {
+ qCDebug(logCL, "Releasing OpenCL context %p", m_context);
+ clReleaseContext(m_context);
+ m_context = 0;
+ }
+ m_device = 0;
+ m_platform = 0;
+}
+
+QT_END_NAMESPACE
diff --git a/src/quickcl/qquickclcontext_p.h b/src/quickcl/qquickclcontext_p.h
new file mode 100644
index 0000000..10bf70d
--- /dev/null
+++ b/src/quickcl/qquickclcontext_p.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick CL module
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQUICKCLCONTEXT_P_H
+#define QQUICKCLCONTEXT_P_H
+
+#include <QtQuickCL/qtquickclglobal.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQuickCLContext
+{
+public:
+ QQuickCLContext();
+ ~QQuickCLContext();
+
+ bool create();
+ void destroy();
+
+ bool isValid() const { return m_context != 0; }
+
+ cl_platform_id platform() const { return m_platform; }
+ cl_device_id device() const { return m_device; }
+ cl_context context() const { return m_context; }
+
+private:
+ cl_platform_id m_platform;
+ cl_device_id m_device;
+ cl_context m_context;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/quickcl/qquickclimagerunnable.cpp b/src/quickcl/qquickclimagerunnable.cpp
new file mode 100644
index 0000000..01a7be1
--- /dev/null
+++ b/src/quickcl/qquickclimagerunnable.cpp
@@ -0,0 +1,340 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick CL module
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qquickclimagerunnable.h"
+#include "qquickclitem.h"
+#include <QSGSimpleTextureNode>
+#include <QSGTextureProvider>
+#include <QOpenGLTexture>
+#include <QOpenGLFunctions>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QQuickCLImageRunnable
+ \brief A QQuickCLItem backend specialized for operating on a single texture from the scenegraph.
+
+ Specialized QQuickCLRunnable for applications wishing to perform
+ OpenCL operations on an OpenCL image object wrapping an OpenGL texture of
+ an Image element - or any other texture provider in the Qt Quick scene -
+ and show the result in the scene.
+
+ The class provides an OpenCL command queue and a simple texture node for
+ the scenegraph. The item providing the texture is read from the associated
+ QQuickCLItem's \c source property by default. This can be overridden by
+ calling setSourcePropertyName().
+
+ By using this specialized class instead of the more generic base
+ QQuickCLRunnable, applications can focus on the kernels and there is no
+ need to manually manage OpenCL image objects, textures, and scenegraph nodes.
+
+ For example, assuming a QQuickCLItem subclass named CLItem, running OpenCL
+ kernels on an image, producing a new output image rendered by CLItem in an
+ accelerated manner without any CPU side readbacks, becomes as simple as the
+ following:
+
+ \badcode
+ Image {
+ id: srcImage
+ source: "image.png"
+ }
+ ...
+ CLItem {
+ source: srcImage
+ }
+ \endcode
+
+ The source can be any texture provider. By enabling layering, the OpenCL
+ kernels can operate on the rendering of an entire sub-tree instead of just
+ a single Image item. In addition, this approach also allows hiding the
+ source sub-tree:
+
+ \badcode
+ Item {
+ id: srcItem
+ layer.enabled: true
+ visible: false
+ ...
+ }
+ CLItem {
+ source: srcItem
+ }
+ \endcode
+
+ Besides image processing scenarios it is also possible to use
+ QQuickCLImageRunnable for computations that produce arbitrary data from an
+ image (for example histogram calculation). Passing the flag NoImageOutput to
+ the constructor will avoid generating an OpenGL texture and corresponding
+ OpenCL image object for the output. Instead, it is up to the runKernel()
+ implementation to emit a signal on the associated QQuickCLItem and pass an
+ object exposing the results of the computation to QML. The visualization is
+ then done by child items since the QQuickCLItem itself does not render
+ anything in the Qt Quick scenegraph in this case, although it is still
+ present as an item having contents.
+ */
+
+/*!
+ \fn void QQuickCLImageRunnable::runKernel(cl_mem inImage, cl_mem outImage, const QSize &size)
+
+ Called when the OpenCL kernel(s) performing the image processing need to be
+ run. \a inImage and \a outImage are ready to be used as input and output
+ \c image2d_t parameters to a kernel. \a size specifies the size of the images.
+
+ \note For QQuickCLImageRunnable instances created with the NoImageOutput
+ flag \a outImage is always \c 0.
+
+ \note QQuickCLImageRunnable is aware of \c cl_khr_gl_event and will invoke
+ glFinish() and clFinish() as necessary in case the extension is not
+ supported. Both will be omitted when the extension is present. However,
+ clFinish() is still invoked regardless of the presence of the extension when
+ either the \c ForceCLFinish or \c Profile flags are set.
+ */
+
+class QQuickCLImageRunnablePrivate
+{
+public:
+ QQuickCLImageRunnablePrivate(QQuickCLItem *item, QQuickCLImageRunnable::Flags flags)
+ : item(item),
+ flags(flags),
+ queue(0),
+ inputTexture(0),
+ outputTexture(0),
+ elapsed(0)
+ {
+ image[0] = image[1] = 0;
+ profEv[0] = profEv[1] = 0;
+ sourcePropertyName = QByteArrayLiteral("source");
+ }
+
+ ~QQuickCLImageRunnablePrivate() {
+ if (image[0])
+ clReleaseMemObject(image[0]);
+ if (image[1])
+ clReleaseMemObject(image[1]);
+ if (queue)
+ clReleaseCommandQueue(queue);
+ delete outputTexture;
+ }
+
+ QQuickCLItem *item;
+ QQuickCLImageRunnable::Flags flags;
+ cl_command_queue queue;
+ cl_mem image[2];
+ QSize textureSize;
+ uint inputTexture;
+ QOpenGLTexture *outputTexture;
+ QByteArray sourcePropertyName;
+ cl_event profEv[2];
+ double elapsed;
+ bool needsExplicitSync;
+};
+
+/*!
+ Constructs a new QQuickCLImageRunnable instance associated with \a item.
+ Special behavior, for example computations producing arbitrary non-image
+ output, can be enabled via \a flags.
+ */
+QQuickCLImageRunnable::QQuickCLImageRunnable(QQuickCLItem *item, Flags flags)
+ : d_ptr(new QQuickCLImageRunnablePrivate(item, flags))
+{
+ Q_D(QQuickCLImageRunnable);
+ cl_int err;
+ cl_command_queue_properties queueProps = flags.testFlag(Profile) ? CL_QUEUE_PROFILING_ENABLE : 0;
+ d->queue = clCreateCommandQueue(item->context(), item->device(), queueProps, &err);
+ if (!d->queue) {
+ qWarning("Failed to create OpenCL command queue: %d", err);
+ return;
+ }
+ d->needsExplicitSync = !item->deviceExtensions().contains(QByteArrayLiteral("cl_khr_gl_event"));
+}
+
+QQuickCLImageRunnable::~QQuickCLImageRunnable()
+{
+ delete d_ptr;
+}
+
+/*!
+ \return the OpenCL command queue.
+ */
+cl_command_queue QQuickCLImageRunnable::commandQueue() const
+{
+ Q_D(const QQuickCLImageRunnable);
+ return d->queue;
+}
+
+/*!
+ Sets the name of the property that is queried from the item that was passed
+ to the constructor. The default value is \c source.
+ */
+void QQuickCLImageRunnable::setSourcePropertyName(const QByteArray &name)
+{
+ Q_D(QQuickCLImageRunnable);
+ d->sourcePropertyName = name;
+}
+
+QSGNode *QQuickCLImageRunnable::update(QSGNode *node)
+{
+ Q_D(QQuickCLImageRunnable);
+ QSGTextureProvider *textureProvider;
+ QSGTexture *texture;
+ QQuickItem *source = d->item->property(d->sourcePropertyName.constData()).value<QQuickItem *>();
+ if (!source
+ || !source->isTextureProvider()
+ || !(textureProvider = source->textureProvider())
+ || !(texture = textureProvider->texture())) {
+ delete node;
+ return 0;
+ }
+
+ QSGDynamicTexture *dtex = qobject_cast<QSGDynamicTexture *>(texture);
+ if (dtex)
+ dtex->updateTexture();
+
+ if (!texture->textureId()) { // the texture provider may not be ready yet, try again later
+ d->item->scheduleUpdate();
+ return node;
+ }
+
+ if (d->inputTexture != uint(texture->textureId())
+ || d->textureSize != texture->textureSize()
+ || (!d->flags.testFlag(NoOutputImage) && !d->outputTexture)) {
+ if (d->image[0])
+ clReleaseMemObject(d->image[0]);
+ d->image[0] = 0;
+ if (d->image[1])
+ clReleaseMemObject(d->image[1]);
+ d->image[1] = 0;
+ delete d->outputTexture;
+ d->outputTexture = 0;
+ delete node;
+ node = 0;
+ }
+
+ cl_int err = 0;
+ if (!d->image[0])
+ d->image[0] = clCreateFromGLTexture2D(d->item->context(), CL_MEM_READ_ONLY, GL_TEXTURE_2D, 0,
+ texture->textureId(), &err);
+ if (!d->image[0]) {
+ if (err == CL_INVALID_GL_OBJECT) // the texture provider may not be ready yet, try again later
+ d->item->scheduleUpdate();
+ else
+ qWarning("Failed to create OpenCL image object from input OpenGL texture: %d", err);
+ return node;
+ }
+
+ d->inputTexture = texture->textureId();
+ d->textureSize = texture->textureSize();
+
+ const int imageCount = d->flags.testFlag(NoOutputImage) ? 1 : 2;
+ if (imageCount == 2) {
+ if (!d->outputTexture)
+ d->outputTexture = new QOpenGLTexture(QImage(d->textureSize, QImage::Format_RGB32));
+
+ if (!d->image[1])
+ d->image[1] = clCreateFromGLTexture2D(d->item->context(), CL_MEM_WRITE_ONLY, GL_TEXTURE_2D, 0,
+ d->outputTexture->textureId(), &err);
+ if (!d->image[1]) {
+ qWarning("Failed to create OpenCL image object for output OpenGL texture: %d", err);
+ return node;
+ }
+ }
+
+ if (d->needsExplicitSync)
+ QOpenGLContext::currentContext()->functions()->glFinish();
+
+ err = clEnqueueAcquireGLObjects(d->queue, imageCount, d->image, 0, 0, 0);
+ if (err != CL_SUCCESS) {
+ qWarning("Failed to queue acquiring the GL textures: %d", err);
+ return node;
+ }
+
+ if (d->flags.testFlag(Profile))
+ if (clEnqueueMarker(d->queue, &d->profEv[0]) != CL_SUCCESS)
+ qWarning("Failed to enqueue profiling marker (start)");
+
+ runKernel(d->image[0], d->image[1], d->textureSize);
+
+ if (d->flags.testFlag(Profile))
+ if (clEnqueueMarker(d->queue, &d->profEv[1]) != CL_SUCCESS)
+ qWarning("Failed to enqueue profiling marker (end)");
+
+ clEnqueueReleaseGLObjects(d->queue, imageCount, d->image, 0, 0, 0);
+
+ if (d->flags.testFlag(ForceCLFinish) || d->needsExplicitSync || d->flags.testFlag(Profile))
+ clFinish(d->queue);
+
+ if (d->flags.testFlag(Profile)) {
+ cl_ulong start = 0, end = 0;
+ err = clGetEventProfilingInfo(d->profEv[0], CL_PROFILING_COMMAND_QUEUED, sizeof(cl_ulong), &start, 0);
+ if (err != CL_SUCCESS)
+ qWarning("Failed to get profiling info for start event: %d", err);
+ err = clGetEventProfilingInfo(d->profEv[1], CL_PROFILING_COMMAND_END, sizeof(cl_ulong), &end, 0);
+ if (err != CL_SUCCESS)
+ qWarning("Failed to get profiling info for end event: %d", err);
+ d->elapsed = double(end - start) / 1000000.0;
+ clReleaseEvent(d->profEv[0]);
+ clReleaseEvent(d->profEv[1]);
+ }
+
+ if (imageCount == 1)
+ return 0;
+
+ QSGSimpleTextureNode *tnode = static_cast<QSGSimpleTextureNode *>(node);
+ if (!tnode) {
+ tnode = new QSGSimpleTextureNode;
+ tnode->setFiltering(QSGTexture::Linear);
+ tnode->setTexture(d->item->window()->createTextureFromId(d->outputTexture->textureId(), d->textureSize));
+ }
+ tnode->setRect(d->item->boundingRect());
+ tnode->markDirty(QSGNode::DirtyMaterial);
+
+ return tnode;
+}
+
+/*!
+ Returns the number of milliseconds spent on OpenCL operations during the
+ last finished invocation of runKernel().
+
+ \note OpenCL command queue profiling must be enabled by passing the \c Profile
+ flag to the constructor.
+ */
+double QQuickCLImageRunnable::elapsed() const
+{
+ Q_D(const QQuickCLImageRunnable);
+ return d->elapsed;
+}
+
+QT_END_NAMESPACE
diff --git a/src/quickcl/qquickclimagerunnable.h b/src/quickcl/qquickclimagerunnable.h
new file mode 100644
index 0000000..8ca32b0
--- /dev/null
+++ b/src/quickcl/qquickclimagerunnable.h
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick CL module
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQUICKCLIMAGERUNNABLE_H
+#define QQUICKCLIMAGERUNNABLE_H
+
+#include <QtQuickCL/qtquickclglobal.h>
+#include <QtQuickCL/qquickclrunnable.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQuickCLImageRunnablePrivate;
+class QQuickCLItem;
+
+class Q_QUICKCL_EXPORT QQuickCLImageRunnable : public QQuickCLRunnable
+{
+ Q_DECLARE_PRIVATE(QQuickCLImageRunnable)
+
+public:
+ enum Flag {
+ NoOutputImage = 0x01,
+ Profile = 0x02,
+ ForceCLFinish = 0x04
+ };
+ Q_DECLARE_FLAGS(Flags, Flag)
+
+ QQuickCLImageRunnable(QQuickCLItem *item, Flags flags = 0);
+ ~QQuickCLImageRunnable();
+
+ cl_command_queue commandQueue() const;
+
+ void setSourcePropertyName(const QByteArray &name);
+
+ double elapsed() const;
+
+protected:
+ virtual void runKernel(cl_mem inImage, cl_mem outImage, const QSize &size) = 0;
+
+private:
+ QSGNode *update(QSGNode *node) Q_DECL_OVERRIDE;
+
+ QQuickCLImageRunnablePrivate *d_ptr;
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QQuickCLImageRunnable::Flags)
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/quickcl/qquickclitem.cpp b/src/quickcl/qquickclitem.cpp
new file mode 100644
index 0000000..fa5933c
--- /dev/null
+++ b/src/quickcl/qquickclitem.cpp
@@ -0,0 +1,385 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick CL module
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qquickclitem.h"
+#include "qquickclcontext_p.h"
+#include <QtCore/QAtomicInt>
+#include <QtCore/QHash>
+#include <QtCore/QFile>
+#include <QtCore/QLoggingCategory>
+#include <QtQuick/private/qquickitem_p.h>
+
+QT_BEGIN_NAMESPACE
+
+Q_DECLARE_LOGGING_CATEGORY(logCL)
+
+/*!
+ \class QQuickCLItem
+
+ \brief QQuickCLItem is a QQuickItem that automatically gets an OpenCL
+ context with the proper platform and device chosen for CL-GL interop.
+
+ Each instance of QQuickCLItem is backed by a corresponding QQuickCLRunnable.
+
+ \note When animating properties that are used in OpenCL kernels, call the
+ \l{QQuickItem::update()}{update()} function (from the gui thread) to
+ trigger updates.
+ */
+
+/*!
+ \class QQuickCLRunnable
+
+ \brief QQuickCLRunnable instances live on the scenegraph's render thread
+ encapsulating OpenCL and related OpenGL resources.
+
+ The constructor, destructor and update() are always invoked on the render
+ thread with the OpenGL context bound and the OpenCL context ready. This
+ allows easy usage of OpenCL and especially OpenGL resources without
+ worrying about lifetime and threading. They can simply be created in the
+ constructor and released in the destructor.
+ */
+
+/*!
+ \fn QSGNode *QQuickCLRunnable::update(QSGNode *node)
+
+ Called on the render thread every time the QQuickCLItem is updated.
+ Semantically equivalent to
+ \l{QQuickItem::updatePaintNode()}{updatePaintNode()}.
+
+ It is up to the implementation to decide what to do here: it can launch
+ OpenCL operations, wait for them to finish, and return a scenegraph node,
+ for example a QSGSimpleTextureNode wrapping the resulting texture.
+
+ Alternatively, it can also launch a longer running CL operation and return
+ \c null or a node providing some temporary content. Then, when the CL
+ operation is finished, \l{QQuickCLItem::scheduleUpdate()}{scheduleUpdate()}
+ is called from an OpenCL event callback to schedule an update for the Quick
+ item, which means eventually invoking this function again. This function
+ can then provide a new node with the results of the computation.
+
+ \note When necessary, future updates for the QQuickCLItem can also be
+ scheduled from this function. However, this requires calling
+ QQuickCLItem::scheduleUpdate() instead of QQuickItem::update().
+ */
+
+/*!
+ \fn QQuickCLRunnable *QQuickCLItem::createCL()
+
+ Factory function invoked on the render thread after initializing OpenCL.
+ */
+
+class QQuickCLItemPrivate : public QQuickItemPrivate
+{
+ Q_DECLARE_PUBLIC(QQuickCLItem)
+
+public:
+ QQuickCLItemPrivate() : clctx(0), clnode(0) { }
+
+ static void CL_CALLBACK eventCallback(cl_event event, cl_int status, void *user_data);
+
+ QQuickCLContext *clctx;
+ QQuickCLRunnable *clnode;
+};
+
+QQuickCLItem::QQuickCLItem(QQuickItem *parent)
+ : QQuickItem(*new QQuickCLItemPrivate, parent)
+{
+ setFlag(ItemHasContents);
+}
+
+/*!
+ \return the selected OpenCL platform. Matches the OpenGL context in use.
+
+ \note The value is only available after the item is first rendered. It is
+ always safe to call this function from QQuickCLRunnable's constructor,
+ destructor and \l{QQuickCLRunnable::update()}{update()} function.
+ */
+cl_platform_id QQuickCLItem::platform() const
+{
+ Q_D(const QQuickCLItem);
+ return d->clctx ? d->clctx->platform() : 0;
+}
+
+/*!
+ \return the selected OpenCL device. Matches the OpenGL context in use.
+
+ \note The value is only available after the item is first rendered. It is
+ always safe to call this function from QQuickCLRunnable's constructor,
+ destructor and \l{QQuickCLRunnable::update()}{update()} function.
+ */
+cl_device_id QQuickCLItem::device() const
+{
+ Q_D(const QQuickCLItem);
+ return d->clctx ? d->clctx->device() : 0;
+}
+
+/*!
+ \return the OpenCL context.
+
+ \note The value is only available after the item is first rendered. It is
+ always safe to call this function from QQuickCLRunnable's constructor,
+ destructor and \l{QQuickCLRunnable::update()}{update()} function.
+ */
+cl_context QQuickCLItem::context() const
+{
+ Q_D(const QQuickCLItem);
+ return d->clctx ? d->clctx->context() : 0;
+}
+
+QSGNode *QQuickCLItem::updatePaintNode(QSGNode *node, UpdatePaintNodeData *)
+{
+ Q_D(QQuickCLItem);
+
+ if (width() <= 0 || height() <= 0) {
+ delete node;
+ return 0;
+ }
+
+ // render thread, initialize CL if not yet done
+ if (!d->clctx) {
+ d->clctx = new QQuickCLContext;
+ if (!d->clctx->create()) {
+ qWarning("Failed to create OpenCL context");
+ delete d->clctx;
+ d->clctx = 0;
+ }
+ }
+
+ if (!d->clctx)
+ return 0;
+
+ if (!d->clnode)
+ d->clnode = createCL();
+
+ return d->clnode ? d->clnode->update(node) : 0;
+}
+
+class ReleaseRunnable : public QRunnable
+{
+public:
+ ReleaseRunnable(QQuickCLContext *clctx, QQuickCLRunnable *clnode) : clctx(clctx), clnode(clnode) { }
+ void run() Q_DECL_OVERRIDE {
+ delete clnode;
+ delete clctx;
+ }
+private:
+ QQuickCLContext *clctx;
+ QQuickCLRunnable *clnode;
+};
+
+void QQuickCLItem::releaseResources()
+{
+ // gui thread, just schedule. NB this and d may be dead by the time the runnable is run
+ Q_D(QQuickCLItem);
+ window()->scheduleRenderJob(new ReleaseRunnable(d->clctx, d->clnode), QQuickWindow::BeforeSynchronizingStage);
+ d->clnode = 0;
+ d->clctx = 0;
+}
+
+void QQuickCLItem::invalidateSceneGraph()
+{
+ // render thread
+ Q_D(QQuickCLItem);
+ delete d->clnode;
+ d->clnode = 0;
+ delete d->clctx;
+ d->clctx = 0;
+}
+
+static const int EV_UPDATE = QEvent::User + 128;
+static const int EV_EVENT = QEvent::User + 129;
+
+class EventCompleteEvent : public QEvent
+{
+public:
+ EventCompleteEvent(cl_event event) : QEvent(QEvent::Type(EV_EVENT)), event(event) { }
+ cl_event event;
+};
+
+bool QQuickCLItem::event(QEvent *e)
+{
+ if (e->type() == EV_UPDATE) {
+ update();
+ return true;
+ } else if (e->type() == EV_EVENT) {
+ EventCompleteEvent *ev = static_cast<EventCompleteEvent *>(e);
+ eventCompleted(ev->event);
+ return true;
+ }
+ return QQuickItem::event(e);
+}
+
+/*!
+ Schedules an update for the item. Unlike \l{QQuickItem::update()}{the base
+ class' update()}, this is safe to be called on any thread, hence it is safe
+ for use from CL event callbacks.
+ */
+void QQuickCLItem::scheduleUpdate()
+{
+ QCoreApplication::postEvent(this, new QEvent(QEvent::Type(EV_UPDATE)));
+}
+
+/*!
+ \return the name of the current platform in use.
+
+ \note This function can only be called from a QQuickCLRunnable's
+ constructor, destructor and \l{QQuickCLRunnable::update()}{update()}
+ function, or after the item has been rendered at least once.
+ */
+QByteArray QQuickCLItem::platformName() const
+{
+ QByteArray name(1024, '\0');
+ clGetPlatformInfo(platform(), CL_PLATFORM_NAME, name.size(), name.data(), 0);
+ name.resize(int(strlen(name.constData())));
+ return name;
+}
+
+/*!
+ \return the list of device extensions.
+
+ \note This function can only be called from a QQuickCLRunnable's
+ constructor, destructor and \l{QQuickCLRunnable::update()}{update()}
+ function, or after the item has been rendered at least once.
+ */
+QByteArray QQuickCLItem::deviceExtensions() const
+{
+ QByteArray ext(8192, '\0');
+ clGetDeviceInfo(device(), CL_DEVICE_EXTENSIONS, ext.size(), ext.data(), 0);
+ ext.resize(int(strlen(ext.constData())));
+ return ext;
+}
+
+/*!
+ Creates and builds an OpenCL program from the source code in \a src.
+
+ \return the cl_program or \c 0 when failed. Errors and build logs are
+ printed to the warning output.
+
+ \note This function can only be called from a QQuickCLRunnable's
+ constructor, destructor and \l{QQuickCLRunnable::update()}{update()}
+ function, or after the item has been rendered at least once.
+ */
+cl_program QQuickCLItem::buildProgram(const QByteArray &src)
+{
+ cl_int err;
+ const char *str = src.constData();
+ cl_program prog = clCreateProgramWithSource(context(), 1, &str, 0, &err);
+ if (!prog) {
+ qWarning("Failed to create OpenCL program: %d", err);
+ qWarning("Source was:\n%s", str);
+ return 0;
+ }
+ cl_device_id dev = device();
+ err = clBuildProgram(prog, 1, &dev, 0, 0, 0);
+ if (err != CL_SUCCESS) {
+ qWarning("Failed to build OpenCL program: %d", err);
+ qWarning("Source was:\n%s", str);
+ QByteArray log;
+ log.resize(8192);
+ clGetProgramBuildInfo(prog, dev, CL_PROGRAM_BUILD_LOG, log.size(), log.data(), 0);
+ qWarning("Build log:\n%s", log.constData());
+ return 0;
+ }
+ return prog;
+}
+
+/*!
+ Creates and builds an OpenCL program from the source file \a filename.
+
+ \sa buildProgram()
+ */
+cl_program QQuickCLItem::buildProgramFromFile(const QString &filename)
+{
+ QFile f(filename);
+ if (!f.open(QIODevice::ReadOnly | QIODevice::Text)) {
+ qWarning("Failed to open OpenCL program source file %s", qPrintable(filename));
+ return 0;
+ }
+ return buildProgram(f.readAll());
+}
+
+struct EventCallbackParam
+{
+ EventCallbackParam(QQuickCLItem *item) : item(item) { }
+ QPointer<QQuickCLItem> item;
+};
+
+/*!
+ Registers an event callback for \a event. The virtual function
+ eventCompleted() will get invoked on the gui/main thread when the event
+ completes.
+
+ This allows easy and safe asynchronous computations because the results can
+ directly be exposed to QML from eventCompleted() due to it running on the
+ gui/main thread. In addition it is guaranteed that eventCompleted() is
+ never called directly from the OpenCL callback function. Special cases like
+ destroying the QQuickCLItem before completing the event are also handled
+ gracefully.
+
+ \note \a event is not released.
+ */
+void QQuickCLItem::watchEvent(cl_event event)
+{
+ EventCallbackParam *param = new EventCallbackParam(this);
+ cl_int err = clSetEventCallback(event, CL_COMPLETE, QQuickCLItemPrivate::eventCallback, param);
+ if (err != CL_SUCCESS)
+ qWarning("Failed to set event callback: %d", err);
+}
+
+/*!
+ Called on the gui/main thread when the \a event watched via watchEvent()
+ completes. The default implementation does nothing.
+ */
+void QQuickCLItem::eventCompleted(cl_event event)
+{
+ Q_UNUSED(event);
+}
+
+void CL_CALLBACK QQuickCLItemPrivate::eventCallback(cl_event event, cl_int status, void *user_data)
+{
+ if (status != CL_COMPLETE)
+ return;
+ EventCallbackParam *param = static_cast<EventCallbackParam *>(user_data);
+ if (!param->item.isNull())
+ QCoreApplication::postEvent(param->item, new EventCompleteEvent(event));
+ delete param;
+}
+
+QQuickCLRunnable::~QQuickCLRunnable()
+{
+}
+
+QT_END_NAMESPACE
diff --git a/src/quickcl/qquickclitem.h b/src/quickcl/qquickclitem.h
new file mode 100644
index 0000000..98ce7fc
--- /dev/null
+++ b/src/quickcl/qquickclitem.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick CL module
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQUICKCLITEM_H
+#define QQUICKCLITEM_H
+
+#include <QtQuickCL/qtquickclglobal.h>
+#include <QtQuickCL/qquickclrunnable.h>
+#include <QtQuick/qquickitem.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQuickCLItemPrivate;
+
+class Q_QUICKCL_EXPORT QQuickCLItem : public QQuickItem
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QQuickCLItem)
+
+public:
+ QQuickCLItem(QQuickItem *parent = 0);
+
+ cl_platform_id platform() const;
+ cl_device_id device() const;
+ cl_context context() const;
+
+ void scheduleUpdate();
+
+ QByteArray platformName() const;
+ QByteArray deviceExtensions() const;
+ cl_program buildProgram(const QByteArray &src);
+ cl_program buildProgramFromFile(const QString &filename);
+
+ void watchEvent(cl_event event);
+ virtual void eventCompleted(cl_event event);
+
+protected:
+ virtual QQuickCLRunnable *createCL() = 0;
+
+private slots:
+ void invalidateSceneGraph(); // called by QQuickWindow, must be a slot
+
+private:
+ QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *) Q_DECL_OVERRIDE;
+ void releaseResources() Q_DECL_OVERRIDE;
+ bool event(QEvent *) Q_DECL_OVERRIDE;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/quickcl/qquickclrunnable.h b/src/quickcl/qquickclrunnable.h
new file mode 100644
index 0000000..3086afd
--- /dev/null
+++ b/src/quickcl/qquickclrunnable.h
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick CL module
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQUICKCLRUNNABLE_H
+#define QQUICKCLRUNNABLE_H
+
+#include <QtQuickCL/qtquickclglobal.h>
+#include <QtQuick/qsgnode.h>
+
+QT_BEGIN_NAMESPACE
+
+class Q_QUICKCL_EXPORT QQuickCLRunnable
+{
+public:
+ virtual ~QQuickCLRunnable();
+ virtual QSGNode *update(QSGNode *node) = 0;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/quickcl/qtquickclglobal.h b/src/quickcl/qtquickclglobal.h
new file mode 100644
index 0000000..1e459eb
--- /dev/null
+++ b/src/quickcl/qtquickclglobal.h
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick CL module
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTQUICKCLGLOBAL_H
+#define QTQUICKCLGLOBAL_H
+
+#include <QtCore/qglobal.h>
+
+#ifdef Q_OS_OSX
+#include <OpenCL/opencl.h>
+#include <OpenGL/OpenGL.h>
+#else
+#include <CL/opencl.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+#ifndef Q_QUICKCL_EXPORT
+# ifndef QT_STATIC
+# if defined(QT_BUILD_QUICKCL_LIB)
+# define Q_QUICKCL_EXPORT Q_DECL_EXPORT
+# else
+# define Q_QUICKCL_EXPORT Q_DECL_IMPORT
+# endif
+# else
+# define Q_QUICKCL_EXPORT
+# endif
+#endif
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/quickcl/quickcl.pro b/src/quickcl/quickcl.pro
new file mode 100644
index 0000000..2a28924
--- /dev/null
+++ b/src/quickcl/quickcl.pro
@@ -0,0 +1,24 @@
+TARGET = QtQuickCL
+QT = core core-private gui gui-private qml-private quick quick-private
+
+load(qt_module)
+
+DEFINES += QT_BUILD_QUICKCL_LIB
+
+HEADERS = \
+ qtquickclglobal.h \
+ qquickclcontext_p.h \
+ qquickclitem.h \
+ qquickclrunnable.h \
+ qquickclimagerunnable.h
+
+SOURCES = \
+ qquickclcontext.cpp \
+ qquickclitem.cpp \
+ qquickclimagerunnable.cpp
+
+QMAKE_DOCS = $$PWD/doc/qtquickcl.qdocconf
+
+osx: LIBS += -framework OpenCL
+unix: !osx: LIBS += -lOpenCL
+win32: !winrt: !wince*: LIBS += -lopengl32 -lOpenCL
diff --git a/src/src.pro b/src/src.pro
new file mode 100644
index 0000000..108b2c0
--- /dev/null
+++ b/src/src.pro
@@ -0,0 +1,3 @@
+TEMPLATE = subdirs
+SUBDIRS += \
+ quickcl