diff options
author | Laszlo Agocs <laszlo.agocs@theqtcompany.com> | 2015-04-17 10:53:25 +0200 |
---|---|---|
committer | Laszlo Agocs <laszlo.agocs@theqtcompany.com> | 2015-04-17 09:43:36 +0000 |
commit | 5051c63b3b818f5fb0ed9f92e74b916ea9d4e723 (patch) | |
tree | c44cd5f423d8e6a8217e7f7557ed9cd79c136bf6 /src | |
parent | 6d073d4e070790d4e9ef707a9deef975e9f70695 (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.qdocconf | 65 | ||||
-rw-r--r-- | src/quickcl/qquickclcontext.cpp | 199 | ||||
-rw-r--r-- | src/quickcl/qquickclcontext_p.h | 67 | ||||
-rw-r--r-- | src/quickcl/qquickclimagerunnable.cpp | 340 | ||||
-rw-r--r-- | src/quickcl/qquickclimagerunnable.h | 82 | ||||
-rw-r--r-- | src/quickcl/qquickclitem.cpp | 385 | ||||
-rw-r--r-- | src/quickcl/qquickclitem.h | 84 | ||||
-rw-r--r-- | src/quickcl/qquickclrunnable.h | 54 | ||||
-rw-r--r-- | src/quickcl/qtquickclglobal.h | 65 | ||||
-rw-r--r-- | src/quickcl/quickcl.pro | 24 | ||||
-rw-r--r-- | src/src.pro | 3 |
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\">©</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 |