summaryrefslogtreecommitdiffstats
path: root/src/openclgl
diff options
context:
space:
mode:
authorRhys Weatherley <rhys.weatherley@nokia.com>2010-04-03 08:51:07 +1000
committerRhys Weatherley <rhys.weatherley@nokia.com>2010-04-03 09:25:40 +1000
commit4606fd8abf865919b94d5645a2051dc9c92e2b09 (patch)
tree7a7df15680741486d10f8a146478bc7154bbba77 /src/openclgl
parent5ee66bb5c79ad8e0d065bb75d4263a51253a60b3 (diff)
Split the OpenGL dependencies out into a separate library.
Eventually we may want to put QtOpenCL into QtGui, so we cannot have any OpenGL dependencies in it.
Diffstat (limited to 'src/openclgl')
-rw-r--r--src/openclgl/openclgl.pro47
-rw-r--r--src/openclgl/openclgl_dep.pri21
-rw-r--r--src/openclgl/qcl_gl_p.h73
-rw-r--r--src/openclgl/qcl_glproxy_p.h77
-rw-r--r--src/openclgl/qclcontextgl.cpp722
-rw-r--r--src/openclgl/qclcontextgl.h128
-rw-r--r--src/openclgl/qcltexture2d.cpp337
-rw-r--r--src/openclgl/qcltexture2d.h90
8 files changed, 1495 insertions, 0 deletions
diff --git a/src/openclgl/openclgl.pro b/src/openclgl/openclgl.pro
new file mode 100644
index 0000000..2c503b0
--- /dev/null
+++ b/src/openclgl/openclgl.pro
@@ -0,0 +1,47 @@
+TEMPLATE = lib
+TARGET = QtOpenCLGL
+QT += opengl
+CONFIG += dll \
+ warn_on
+win32 {
+ DESTDIR = ../../bin
+ !static:DEFINES += QT_MAKEDLL
+}
+else:DESTDIR = ../../lib
+
+macx {
+ LIBS += -framework OpenCL
+} else {
+ !isEmpty(QMAKE_INCDIR_OPENCL) {
+ QMAKE_CXXFLAGS += -I$$QMAKE_INCDIR_OPENCL
+ }
+ !isEmpty(QMAKE_LIBDIR_OPENCL) {
+ LIBS += -L$$QMAKE_LIBDIR_OPENCL
+ }
+ !isEmpty(QMAKE_LIBS_OPENCL) {
+ LIBS += $$QMAKE_LIBS_OPENCL
+ } else {
+ LIBS += -lOpenCL
+ }
+}
+
+no_cl_gl {
+ DEFINES += QT_NO_CL_OPENGL
+}
+
+INCLUDEPATH += $$PWD/../opencl
+
+HEADERS += \
+ qclcontextgl.h \
+ qcltexture2d.h
+
+SOURCES += \
+ qclcontextgl.cpp \
+ qcltexture2d.cpp
+
+PRIVATE_HEADERS += \
+ qcl_gl_p.h \
+ qcl_glproxy_p.h
+
+HEADERS += $$PRIVATE_HEADERS
+DEFINES += QT_BUILD_CLGL_LIB
diff --git a/src/openclgl/openclgl_dep.pri b/src/openclgl/openclgl_dep.pri
new file mode 100644
index 0000000..d8e8906
--- /dev/null
+++ b/src/openclgl/openclgl_dep.pri
@@ -0,0 +1,21 @@
+INCLUDEPATH += $$PWD $$PWD/../opencl
+macx {
+ LIBS += -lQtOpenCLGL -lQtOpenCL -framework OpenCL
+} else {
+ LIBS += -lQtOpenCLGL -lQtOpenCL
+ !isEmpty(QMAKE_INCDIR_OPENCL) {
+ QMAKE_CXXFLAGS += -I$$QMAKE_INCDIR_OPENCL
+ }
+ !isEmpty(QMAKE_LIBDIR_OPENCL) {
+ LIBS += -L$$QMAKE_LIBDIR_OPENCL
+ }
+ !isEmpty(QMAKE_LIBS_OPENCL) {
+ LIBS += $$QMAKE_LIBS_OPENCL
+ } else {
+ LIBS += -lOpenCL
+ }
+}
+QT += opengl
+no_cl_gl {
+ DEFINES += QT_NO_CL_OPENGL
+}
diff --git a/src/openclgl/qcl_gl_p.h b/src/openclgl/qcl_gl_p.h
new file mode 100644
index 0000000..361b893
--- /dev/null
+++ b/src/openclgl/qcl_gl_p.h
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtOpenCL module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QCL_GL_P_H
+#define QCL_GL_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#if !defined(QT_NO_CL_OPENGL)
+
+#include <QtOpenGL/qgl.h>
+#if defined(__APPLE__) || defined(__MACOSX)
+#include <OpenGL/OpenGL.h>
+#include <OpenCL/cl_platform.h>
+#include <OpenCL/cl.h>
+#include <OpenCL/cl_gl.h>
+#include <CGLDevice.h>
+#else
+#include <CL/cl_platform.h>
+#include <CL/cl.h>
+#include <CL/cl_gl.h>
+#endif
+
+#endif
+
+#endif
diff --git a/src/openclgl/qcl_glproxy_p.h b/src/openclgl/qcl_glproxy_p.h
new file mode 100644
index 0000000..5dbc4fb
--- /dev/null
+++ b/src/openclgl/qcl_glproxy_p.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtOpenCL module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QCL_GLPROXY_P_H
+#define QCL_GLPROXY_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtOpenGL/qgl.h>
+
+QT_BEGIN_NAMESPACE
+
+// Copied from <QtOpenGL/private/qgl_p.h>. Hopefully won't be
+// necessary in future versions of Qt.
+class Q_OPENGL_EXPORT QGLSignalProxy : public QObject
+{
+ Q_OBJECT
+public:
+ QGLSignalProxy() : QObject() {}
+ void emitAboutToDestroyContext(const QGLContext *context) {
+ emit aboutToDestroyContext(context);
+ }
+ static QGLSignalProxy *instance();
+Q_SIGNALS:
+ void aboutToDestroyContext(const QGLContext *context);
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/openclgl/qclcontextgl.cpp b/src/openclgl/qclcontextgl.cpp
new file mode 100644
index 0000000..58b3da2
--- /dev/null
+++ b/src/openclgl/qclcontextgl.cpp
@@ -0,0 +1,722 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtOpenCL module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qclcontextgl.h"
+#include "qcl_gl_p.h"
+#include <QtCore/qdebug.h>
+#include <QtCore/qvarlengtharray.h>
+
+#if !defined(QT_NO_CL_OPENGL)
+#if defined(QT_OPENGL_ES_2)
+#include <EGL/egl.h>
+#elif defined(QT_OPENGL_ES)
+#include <GLES/egl.h>
+#elif defined(Q_WS_X11)
+#include <GL/glx.h>
+#endif
+#endif
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QCLContextGL
+ \brief The QCLContextGL class represents an OpenCL context that is suitable for use with OpenGL objects.
+ \since 4.7
+ \ingroup opencl
+*/
+
+class QCLContextGLPrivate
+{
+public:
+ QCLContextGLPrivate()
+ : supportsSharing(false)
+ {
+ }
+
+ bool supportsSharing;
+};
+
+/*!
+ Constructs a new OpenCL context object that is suitable for use
+ with OpenGL objects.
+*/
+QCLContextGL::QCLContextGL()
+ : QCLContext(), d_ptr(new QCLContextGLPrivate())
+{
+}
+
+/*!
+ Destroys this OpenCL context.
+*/
+QCLContextGL::~QCLContextGL()
+{
+}
+
+extern "C" {
+
+static void qt_clgl_context_notify(const char *errinfo,
+ const void *private_info,
+ size_t cb,
+ void *user_data)
+{
+ Q_UNUSED(private_info);
+ Q_UNUSED(cb);
+ Q_UNUSED(user_data);
+ qWarning() << "OpenCL/GL context notification: " << errinfo;
+}
+
+};
+
+#define CL_GL_CONTEXT_KHR 0x2008
+#define CL_EGL_DISPLAY_KHR 0x2009
+#define CL_GLX_DISPLAY_KHR 0x200A
+#define CL_WGL_HDC_KHR 0x200B
+#define CL_CGL_SHAREGROUP_KHR 0x200C
+
+/*!
+ Creates an OpenCL context that is compatible with the current
+ QGLContext. Returns false if there is no OpenGL context current or
+ the OpenCL context could not be created for some reason.
+
+ This function will first try to create a QCLDevice::GPU device,
+ and will then fall back to QCLDevice::Default if a GPU is not found.
+
+ \sa supportsObjectSharing()
+*/
+bool QCLContextGL::create()
+{
+ Q_D(QCLContextGL);
+
+ // Bail out if the context already exists.
+ if (isCreated())
+ return true;
+
+ // Bail out if we don't have an OpenGL context.
+ if (!QGLContext::currentContext()) {
+ qWarning() << "QCLContextGL::create: needs a current GL context";
+ setLastError(CL_INVALID_CONTEXT);
+ return false;
+ }
+
+ // Find the first gpu device.
+ QCLPlatform plat = platform();
+ QList<QCLDevice> devices;
+ cl_device_type deviceType = CL_DEVICE_TYPE_GPU;
+ if (plat.isNull()) {
+ devices = QCLDevice::devices(QCLDevice::GPU);
+ if (devices.isEmpty()) {
+ devices = QCLDevice::devices(QCLDevice::Default);
+ deviceType = CL_DEVICE_TYPE_DEFAULT;
+ }
+ } else {
+ devices = QCLDevice::devices(QCLDevice::GPU, plat);
+ if (devices.isEmpty()) {
+ devices = QCLDevice::devices(QCLDevice::Default, plat);
+ deviceType = CL_DEVICE_TYPE_DEFAULT;
+ }
+ }
+ if (devices.isEmpty()) {
+ qWarning() << "QCLContextGL::create: no gpu devices found";
+ setLastError(CL_DEVICE_NOT_FOUND);
+ return false;
+ }
+ QCLDevice gpu = devices[0];
+
+ // Add the platform identifier to the properties, if present.
+ QVarLengthArray<cl_context_properties> properties;
+ if (!plat.isNull()) {
+ properties.append(CL_CONTEXT_PLATFORM);
+ properties.append(cl_context_properties(plat.platformId()));
+ }
+
+ bool hasSharing = false;
+#ifndef QT_NO_CL_OPENGL
+ // Determine what kind of OpenCL-OpenGL sharing we have and enable it.
+ QStringList extensions = gpu.extensions();
+#if defined(__APPLE__) || defined(__MACOSX)
+ bool appleSharing = gpu.hasExtension("cl_apple_gl_sharing");
+ if (appleSharing) {
+ CGLContextObj cglContext = CGLGetCurrentContext();
+ CGLShareGroupObj cglShareGroup = CGLGetShareGroup(cglContext);
+ properties.append(CL_CGL_SHAREGROUP_KHR);
+ properties.append(cl_context_properties(cglShareGroup));
+ hasSharing = true;
+ }
+#else
+ bool khrSharing = gpu.hasExtension("cl_khr_gl_sharing");
+#if defined(QT_OPENGL_ES_2) || defined(QT_OPENGL_ES)
+ if (khrSharing) {
+ properties.append(CL_EGL_DISPLAY_KHR);
+ properties.append(cl_context_properties(eglGetCurrentDisplay()));
+#ifdef EGL_OPENGL_ES_API
+ eglBindAPI(EGL_OPENGL_ES_API);
+#endif
+ properties.append(CL_GL_CONTEXT_KHR);
+ properties.append(cl_context_properties(eglGetCurrentContext()));
+ hasSharing = true;
+ }
+#elif defined(Q_WS_X11)
+ if (khrSharing) {
+ properties.append(CL_GLX_DISPLAY_KHR);
+ properties.append(cl_context_properties(glXGetCurrentDisplay()));
+ properties.append(CL_GL_CONTEXT_KHR);
+ properties.append(cl_context_properties(glXGetCurrentContext()));
+ hasSharing = true;
+ }
+#else
+ // Needs to be ported to other platforms.
+ if (khrSharing)
+ qWarning() << "QCLContextGL::create: do not know how to enable sharing";
+#endif
+#endif
+#endif // !QT_NO_CL_OPENGL
+
+ // Create the OpenCL context.
+ cl_context id;
+ cl_int error;
+ if (!properties.isEmpty()) {
+ id = clCreateContextFromType
+ (properties.data(), deviceType,
+ qt_clgl_context_notify, 0, &error);
+ } else {
+ id = clCreateContextFromType
+ (0, deviceType, qt_clgl_context_notify, 0, &error);
+ }
+ if (!id && error == CL_INVALID_PLATFORM && plat.isNull()) {
+ // Some OpenCL implementations seem to fail if a non-specific
+ // platform is supplied. Try again with an explicit device.
+ cl_device_id dev = gpu.deviceId();
+ if (!properties.isEmpty()) {
+ id = clCreateContext
+ (properties.data(), 1, &dev,
+ qt_clgl_context_notify, 0, &error);
+ }
+ if (!id && error == CL_INVALID_VALUE) {
+ // One more try - remove the GL properties.
+ id = clCreateContext
+ (0, 1, &dev, qt_clgl_context_notify, 0, &error);
+ hasSharing = false;
+ }
+ }
+ setLastError(error);
+ if (id == 0) {
+ qWarning() << "QCLContextGL::create:" << errorName(error);
+ d->supportsSharing = false;
+ } else {
+ d->supportsSharing = hasSharing;
+ setContextId(id);
+ clReleaseContext(id); // setContextId() adds an extra reference.
+ }
+ return id != 0;
+}
+
+/*!
+ Returns true if this OpenCL context supports object sharing
+ with OpenGL; false otherwise.
+
+ \sa createGLBuffer(), createTexture2D(), createTexture3D()
+ \sa createRenderbuffer()
+*/
+bool QCLContextGL::supportsObjectSharing() const
+{
+ Q_D(const QCLContextGL);
+ return d->supportsSharing;
+}
+
+/*!
+ Creates an OpenCL memory buffer from the OpenGL buffer object
+ \a bufobj, with the specified \a access mode.
+
+ This function will only work if supportsObjectSharing() is true.
+*/
+QCLBuffer QCLContextGL::createGLBuffer(GLuint bufobj, QCL::Access access)
+{
+#ifndef QT_NO_CL_OPENGL
+ cl_int error = CL_INVALID_CONTEXT;
+ cl_mem_flags flags = cl_mem_flags(access);
+ cl_mem mem = clCreateFromGLBuffer
+ (contextId(), flags, bufobj, &error);
+ reportError("QCLContextGL::createGLBuffer:", error);
+ if (mem)
+ return QCLBuffer(this, mem);
+ else
+ return QCLBuffer();
+#else
+ Q_UNUSED(bufobj);
+ Q_UNUSED(access);
+ reportError("QCLContextGL::createGLBuffer:", CL_INVALID_VALUE);
+ return QCLBuffer();
+#endif
+}
+
+#if QT_VERSION >= 0x040700 || defined(Q_QDOC)
+
+/*!
+ \overload
+
+ Creates an OpenCL memory buffer from the OpenGL buffer object
+ \a bufobj, with the specified \a access mode.
+
+ This function will only work if supportsObjectSharing() is true.
+*/
+QCLBuffer QCLContextGL::createGLBuffer(QGLBuffer *bufobj, QCL::Access access)
+{
+ if (!bufobj)
+ return QCLBuffer();
+ return createGLBuffer(GLuint(bufobj->bufferId()), access);
+}
+
+#endif
+
+/*!
+ Creates a 2D OpenCL image object from the specified \a mipmapLevel,
+ OpenGL \a texture object, and \a access mode.
+
+ The \a type must be one of \c{GL_TEXTURE_2D},
+ \c{GL_TEXTURE_CUBE_MAP_POSITIVE_X}, \c{GL_TEXTURE_CUBE_MAP_POSITIVE_Y},
+ \c{GL_TEXTURE_CUBE_MAP_POSITIVE_Z}, \c{GL_TEXTURE_CUBE_MAP_NEGATIVE_X},
+ \c{GL_TEXTURE_CUBE_MAP_NEGATIVE_Y}, \c{GL_TEXTURE_CUBE_MAP_NEGATIVE_Z},
+ or \c{GL_TEXTURE_RECTANGLE}. The \a texture does not need to be
+ bound to an OpenGL texture target.
+
+ This function will only work if supportsObjectSharing() is true.
+
+ \sa createTexture3D(), createRenderbuffer()
+*/
+QCLImage2D QCLContextGL::createTexture2D
+ (GLenum type, GLuint texture, GLint mipmapLevel, QCL::Access access)
+{
+#ifndef QT_NO_CL_OPENGL
+ cl_int error = CL_INVALID_CONTEXT;
+ cl_mem_flags flags = cl_mem_flags(access);
+ cl_mem mem = clCreateFromGLTexture2D
+ (contextId(), flags, type, mipmapLevel, texture, &error);
+ reportError("QCLContextGL::createGLTexture2D:", error);
+ if (mem)
+ return QCLImage2D(this, mem);
+ else
+ return QCLImage2D();
+#else
+ Q_UNUSED(type);
+ Q_UNUSED(texture);
+ Q_UNUSED(mipmapLevel);
+ Q_UNUSED(access);
+ reportError("QCLContextGL::createGLTexture2D:", CL_INVALID_VALUE);
+ return QCLImage2D();
+#endif
+}
+
+/*!
+ \overload
+
+ Creates a 2D OpenCL image object from the specified OpenGL
+ \a texture object, and the \a access mode. If texture type is
+ assumed to be \c{GL_TEXTURE_2D} and the mipmap level is
+ assumed to be 0.
+
+ This function will only work if supportsObjectSharing() is true.
+*/
+QCLImage2D QCLContextGL::createTexture2D(GLuint texture, QCL::Access access)
+{
+ return createTexture2D(GL_TEXTURE_2D, texture, 0, access);
+}
+
+#ifndef GL_TEXTURE_3D
+#define GL_TEXTURE_3D 0x806F
+#endif
+
+/*!
+ Creates a 3D OpenCL image object from the specified \a mipmapLevel,
+ OpenGL \a texture object, and \a access mode.
+
+ The \a type must be \c{GL_TEXTURE_3D}. The \a texture does not need
+ to be bound to an OpenGL texture target.
+
+ This function will only work if supportsObjectSharing() is true.
+
+ \sa createTexture2D()
+*/
+QCLImage3D QCLContextGL::createTexture3D
+ (GLenum type, GLuint texture, GLint mipmapLevel, QCL::Access access)
+{
+#ifndef QT_NO_CL_OPENGL
+ cl_int error = CL_INVALID_CONTEXT;
+ cl_mem_flags flags = cl_mem_flags(access);
+ cl_mem mem = clCreateFromGLTexture3D
+ (contextId(), flags, type, mipmapLevel, texture, &error);
+ reportError("QCLContextGL::createGLTexture3D:", error);
+ if (mem)
+ return QCLImage3D(this, mem);
+ else
+ return QCLImage3D();
+#else
+ Q_UNUSED(type);
+ Q_UNUSED(texture);
+ Q_UNUSED(mipmapLevel);
+ Q_UNUSED(access);
+ reportError("QCLContextGL::createGLTexture3D:", CL_INVALID_VALUE);
+ return QCLImage3D();
+#endif
+}
+
+/*!
+ \overload
+
+ Creates a 3D OpenCL image object from the specified OpenGL
+ \a texture object, and \a access mode. If texture type is
+ assumed to be \c{GL_TEXTURE_3D} and the mipmap level is
+ assumed to be 0.
+
+ This function will only work if supportsObjectSharing() is true.
+*/
+QCLImage3D QCLContextGL::createTexture3D(GLuint texture, QCL::Access access)
+{
+ return createTexture3D(GL_TEXTURE_3D, texture, 0, access);
+}
+
+/*!
+ Creates a 2D OpenCL image object from the specified OpenGL
+ \a renderbuffer object, and the \a access mode.
+
+ This function will only work if supportsObjectSharing() is true.
+
+ \sa createTexture2D()
+*/
+QCLImage2D QCLContextGL::createRenderbuffer
+ (GLuint renderbuffer, QCL::Access access)
+{
+#ifndef QT_NO_CL_OPENGL
+ cl_int error = CL_INVALID_CONTEXT;
+ cl_mem_flags flags = cl_mem_flags(access);
+ cl_mem mem = clCreateFromGLRenderbuffer
+ (contextId(), flags, renderbuffer, &error);
+ reportError("QCLContextGL::createGLRenderbuffer:", error);
+ if (mem)
+ return QCLImage2D(this, mem);
+ else
+ return QCLImage2D();
+#else
+ Q_UNUSED(renderbuffer);
+ Q_UNUSED(access);
+ reportError("QCLContextGL::createRenderbuffer:", CL_INVALID_VALUE);
+ return QCLImage2D();
+#endif
+}
+
+/*!
+ \internal
+*/
+void QCLContextGL::reportError(const char *name, cl_int error)
+{
+ setLastError(error);
+ if (error != CL_SUCCESS)
+ qWarning() << name << QCLContext::errorName(error);
+}
+
+#ifdef Q_MAC_COMPAT_GL_FUNCTIONS
+
+/*!
+ \internal
+*/
+QCLBuffer QCLContextGL::createGLBuffer
+ (QMacCompatGLuint bufobj, QCL::Access access)
+{
+ return createGLBuffer(GLuint(bufobj), access);
+}
+
+/*!
+ \internal
+*/
+QCLImage2D QCLContextGL::createTexture2D
+ (QMacCompatGLenum type, QMacCompatGLuint texture,
+ QMacCompatGLint mipmapLevel, QCL::Access access)
+{
+ return createTexture2D(GLenum(type), GLuint(texture),
+ GLint(mipmapLevel), access);
+}
+
+/*!
+ \internal
+*/
+QCLImage2D QCLContextGL::createTexture2D
+ (QMacCompatGLuint texture, QCL::Access access)
+{
+ return createTexture2D(GLenum(GL_TEXTURE_2D), GLuint(texture),
+ GLint(0), access);
+}
+
+/*!
+ \internal
+*/
+QCLImage3D QCLContextGL::createTexture3D
+ (QMacCompatGLenum type, QMacCompatGLuint texture,
+ QMacCompatGLint mipmapLevel, QCL::Access access)
+{
+ return createTexture3D(GLenum(type), GLuint(texture),
+ GLint(mipmapLevel), access);
+}
+
+/*!
+ \internal
+*/
+QCLImage3D QCLContextGL::createTexture3D
+ (QMacCompatGLuint texture, QCL::Access access)
+{
+ return createTexture3D(GLenum(GL_TEXTURE_3D), GLuint(texture),
+ GLint(0), access);
+}
+
+/*!
+ \internal
+*/
+QCLImage2D QCLContextGL::createRenderbuffer
+ (QMacCompatGLuint renderbuffer, QCL::Access access)
+{
+ return createRenderbuffer(GLuint(renderbuffer), access);
+}
+
+#endif
+
+/*!
+ Returns true if the OpenCL \a buffer object is also an OpenGL
+ buffer object; false otherwise.
+*/
+bool QCLContextGL::isGLBuffer(const QCLBuffer &buffer)
+{
+#ifndef QT_NO_CL_OPENGL
+ cl_gl_object_type objectType;
+ if (clGetGLObjectInfo
+ (buffer.memoryId(), &objectType, 0) != CL_SUCCESS)
+ return false;
+ return objectType == CL_GL_OBJECT_BUFFER;
+#else
+ return false;
+#endif
+}
+
+/*!
+ Returns true if the 2D OpenCL \a image object is also an OpenGL
+ 2D texture object; false otherwise.
+
+ \sa isRenderbuffer(), isTexture3D()
+*/
+bool QCLContextGL::isTexture2D(const QCLImage2D &image)
+{
+#ifndef QT_NO_CL_OPENGL
+ cl_gl_object_type objectType;
+ if (clGetGLObjectInfo
+ (image.memoryId(), &objectType, 0) != CL_SUCCESS)
+ return false;
+ return objectType == CL_GL_OBJECT_TEXTURE2D;
+#else
+ return false;
+#endif
+}
+
+/*!
+ Returns true if the 3D OpenCL \a image object is also an OpenGL
+ 3D texture object; false otherwise.
+
+ \sa isTexture2D()
+*/
+bool QCLContextGL::isTexture3D(const QCLImage3D &image)
+{
+#ifndef QT_NO_CL_OPENGL
+ cl_gl_object_type objectType;
+ if (clGetGLObjectInfo
+ (image.memoryId(), &objectType, 0) != CL_SUCCESS)
+ return false;
+ return objectType == CL_GL_OBJECT_TEXTURE3D;
+#else
+ return false;
+#endif
+}
+
+/*!
+ Returns true if the 2D OpenCL \a image object is also an OpenGL
+ renderbuffer object; false otherwise.
+
+ \sa isTexture2D()
+*/
+bool QCLContextGL::isRenderbuffer(const QCLImage2D &image)
+{
+#ifndef QT_NO_CL_OPENGL
+ cl_gl_object_type objectType;
+ if (clGetGLObjectInfo
+ (image.memoryId(), &objectType, 0) != CL_SUCCESS)
+ return false;
+ return objectType == CL_GL_OBJECT_RENDERBUFFER;
+#else
+ return false;
+#endif
+}
+
+/*!
+ Acquires access to the OpenGL object behind the OpenCL memory
+ object \a mem. This function must be called before performing
+ an OpenCL operation on any OpenGL memory object.
+
+ Returns an event object that can be used to wait for the
+ request to finish. The request is executed on the active
+ command queue for this context.
+
+ \sa release()
+*/
+QCLEvent QCLContextGL::acquire(const QCLMemoryObject &mem)
+{
+#ifndef QT_NO_CL_OPENGL
+ cl_event event;
+ cl_mem id = mem.memoryId();
+ cl_int error = clEnqueueAcquireGLObjects
+ (commandQueue().queueId(), 1, &id, 0, 0, &event);
+ reportError("QCLContextGL::acquire:", error);
+ if (error == CL_SUCCESS)
+ return QCLEvent(event);
+ else
+ return QCLEvent();
+#else
+ return QCLEvent();
+#endif
+}
+
+/*!
+ \overload
+
+ Acquires access to the OpenGL object behind the OpenCL memory
+ object \a mem. This function must be called before performing
+ an OpenCL operation on any OpenGL memory object.
+
+ The request will not start until all of the events in \a after
+ have been signaled as finished.
+
+ Returns an event object that can be used to wait for the
+ request to finish. The request is executed on the active
+ command queue for this context.
+
+ \sa release()
+*/
+QCLEvent QCLContextGL::acquire
+ (const QCLMemoryObject &mem, const QCLEventList &after)
+{
+#ifndef QT_NO_CL_OPENGL
+ cl_event event;
+ cl_mem id = mem.memoryId();
+ cl_int error = clEnqueueAcquireGLObjects
+ (commandQueue().queueId(), 1, &id,
+ after.size(), after.eventData(), &event);
+ reportError("QCLContextGL::acquire(after):", error);
+ if (error == CL_SUCCESS)
+ return QCLEvent(event);
+ else
+ return QCLEvent();
+#else
+ Q_UNUSED(after);
+ return QCLEvent();
+#endif
+}
+
+/*!
+ Releases access to the OpenGL object behind the OpenCL memory
+ object \a mem. This function must be called after performing
+ an OpenCL operation on any OpenGL memory object, and before
+ performing OpenGL operations on the object.
+
+ Returns an event object that can be used to wait for the
+ request to finish. The request is executed on the active
+ command queue for this context.
+
+ \sa acquire()
+*/
+QCLEvent QCLContextGL::release(const QCLMemoryObject &mem)
+{
+#ifndef QT_NO_CL_OPENGL
+ cl_event event;
+ cl_mem id = mem.memoryId();
+ cl_int error = clEnqueueReleaseGLObjects
+ (commandQueue().queueId(), 1, &id, 0, 0, &event);
+ reportError("QCLContextGL::release:", error);
+ if (error == CL_SUCCESS)
+ return QCLEvent(event);
+ else
+ return QCLEvent();
+#else
+ return QCLEvent();
+#endif
+}
+
+/*!
+ \overload
+
+ Releases access to the OpenGL object behind the OpenCL memory
+ object \a mem. This function must be called after performing
+ an OpenCL operation on any OpenGL memory object, and before
+ performing OpenGL operations on the object.
+
+ The request will not start until all of the events in \a after
+ have been signaled as finished.
+
+ Returns an event object that can be used to wait for the
+ request to finish. The request is executed on the active
+ command queue for this context.
+
+ \sa acquire()
+*/
+QCLEvent QCLContextGL::release
+ (const QCLMemoryObject &mem, const QCLEventList &after)
+{
+#ifndef QT_NO_CL_OPENGL
+ cl_event event;
+ cl_mem id = mem.memoryId();
+ cl_int error = clEnqueueReleaseGLObjects
+ (commandQueue().queueId(), 1, &id,
+ after.size(), after.eventData(), &event);
+ reportError("QCLContextGL::release(after):", error);
+ if (error == CL_SUCCESS)
+ return QCLEvent(event);
+ else
+ return QCLEvent();
+#else
+ Q_UNUSED(after);
+ return QCLEvent();
+#endif
+}
+
+QT_END_NAMESPACE
diff --git a/src/openclgl/qclcontextgl.h b/src/openclgl/qclcontextgl.h
new file mode 100644
index 0000000..0d5bcea
--- /dev/null
+++ b/src/openclgl/qclcontextgl.h
@@ -0,0 +1,128 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtOpenCL module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QCLCONTEXTGL_H
+#define QCLCONTEXTGL_H
+
+#include "qclcontext.h"
+#include <QtOpenGL/qgl.h>
+#if QT_VERSION >= 0x040700
+#include <QtOpenGL/qglbuffer.h>
+#endif
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(CL)
+
+class QCLContextGLPrivate;
+
+// Note: this class probably should be in the QtOpenGL library.
+class Q_CLGL_EXPORT QCLContextGL : public QCLContext
+{
+public:
+ QCLContextGL();
+ ~QCLContextGL();
+
+ bool create();
+
+ bool supportsObjectSharing() const;
+
+ QCLBuffer createGLBuffer(GLuint bufobj, QCL::Access access);
+#if QT_VERSION >= 0x040700 || defined(Q_QDOC)
+ QCLBuffer createGLBuffer(QGLBuffer *bufobj, QCL::Access access);
+#endif
+
+ QCLImage2D createTexture2D
+ (GLenum type, GLuint texture, GLint mipmapLevel, QCL::Access access);
+ QCLImage2D createTexture2D(GLuint texture, QCL::Access access);
+
+ QCLImage3D createTexture3D
+ (GLenum type, GLuint texture, GLint mipmapLevel, QCL::Access access);
+ QCLImage3D createTexture3D(GLuint texture, QCL::Access access);
+
+ QCLImage2D createRenderbuffer(GLuint renderbuffer, QCL::Access access);
+
+#ifdef Q_MAC_COMPAT_GL_FUNCTIONS
+ QCLBuffer createGLBuffer(QMacCompatGLuint bufobj, QCL::Access access);
+
+ QCLImage2D createTexture2D
+ (QMacCompatGLenum type, QMacCompatGLuint texture,
+ QMacCompatGLint mipmapLevel, QCL::Access access);
+ QCLImage2D createTexture2D(QMacCompatGLuint texture, QCL::Access access);
+
+ QCLImage3D createTexture3D
+ (QMacCompatGLenum type, QMacCompatGLuint texture,
+ QMacCompatGLint mipmapLevel, QCL::Access access);
+ QCLImage3D createTexture3D(QMacCompatGLuint texture, QCL::Access access);
+
+ QCLImage2D createRenderbuffer
+ (QMacCompatGLuint renderbuffer, QCL::Access access);
+#endif
+
+ static bool isGLBuffer(const QCLBuffer &buffer);
+ static bool isTexture2D(const QCLImage2D &image);
+ static bool isTexture3D(const QCLImage3D &image);
+ static bool isRenderbuffer(const QCLImage2D &image);
+
+ QCLEvent acquire(const QCLMemoryObject &mem);
+ QCLEvent acquire
+ (const QCLMemoryObject &mem, const QCLEventList &after);
+
+ QCLEvent release(const QCLMemoryObject &mem);
+ QCLEvent release
+ (const QCLMemoryObject &mem, const QCLEventList &after);
+
+private:
+ QScopedPointer<QCLContextGLPrivate> d_ptr;
+
+ Q_DISABLE_COPY(QCLContextGL)
+ Q_DECLARE_PRIVATE(QCLContextGL)
+
+ void reportError(const char *name, cl_int error);
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/openclgl/qcltexture2d.cpp b/src/openclgl/qcltexture2d.cpp
new file mode 100644
index 0000000..32d4da9
--- /dev/null
+++ b/src/openclgl/qcltexture2d.cpp
@@ -0,0 +1,337 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtOpenCL module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qcltexture2d.h"
+#include "qclcontextgl.h"
+#include "qcl_glproxy_p.h"
+#if QT_VERSION >= 0x040700 && !defined(QT_OPENGL_ES)
+#include <QtOpenGL/qglbuffer.h>
+#define USE_PIXEL_UNPACK_BUFFERS 1
+#endif
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QCLTexture2D
+ \brief The QCLTexture2D class represents a 2D OpenCL texture object.
+ \since 4.7
+ \ingroup opencl
+
+ Normally applications render into OpenGL textures by calling
+ QCLContextGL::createTexture2D() to wrap an existing texture identifier
+ with a QCLImage2D object. However, some systems do not support
+ the OpenCL/OpenGL sharing mechanisms that are needed to make that work.
+
+ QCLTexture2D abstracts the creation and management of \c{GL_RGBA}
+ textures so that applications can render into them with OpenCL
+ kernels without needing to implement special handling for
+ OpenCL implementations that lack sharing.
+*/
+
+class QCLTexture2DPrivate : public QObject
+{
+ Q_OBJECT
+public:
+ QCLTexture2DPrivate()
+ : context(0)
+ , clContext(0)
+ , textureId(0)
+ , directRender(false)
+#ifdef USE_PIXEL_UNPACK_BUFFERS
+ , pixelBuffer(0)
+#endif
+ {
+ }
+ ~QCLTexture2DPrivate()
+ {
+#ifdef USE_PIXEL_UNPACK_BUFFERS
+ delete pixelBuffer;
+#endif
+ }
+
+ const QGLContext *context;
+ QCLContextGL *clContext;
+ GLuint textureId;
+ QSize size;
+ bool directRender;
+#ifdef USE_PIXEL_UNPACK_BUFFERS
+ QGLBuffer *pixelBuffer;
+#endif
+
+ void setContextAndId(const QGLContext *ctx, GLuint id);
+
+private slots:
+ void aboutToDestroyContext(const QGLContext *ctx);
+};
+
+void QCLTexture2DPrivate::aboutToDestroyContext(const QGLContext *ctx)
+{
+ if (context == ctx) {
+ context = 0;
+ textureId = 0;
+ }
+}
+
+void QCLTexture2DPrivate::setContextAndId(const QGLContext *ctx, GLuint id)
+{
+ context = ctx;
+ textureId = id;
+ connect(QGLSignalProxy::instance(),
+ SIGNAL(aboutToDestroyContext(const QGLContext *)),
+ this,
+ SLOT(aboutToDestroyContext(const QGLContext *)));
+}
+
+/*!
+ Constructs an uninitialized OpenCL texture object.
+*/
+QCLTexture2D::QCLTexture2D()
+ : QCLImage2D(), d_ptr(new QCLTexture2DPrivate())
+{
+}
+
+/*!
+ Destroys this OpenCL texture object.
+*/
+QCLTexture2D::~QCLTexture2D()
+{
+ destroy();
+}
+
+/*!
+ Constructs an OpenCL texture of \a size in \a context.
+ Returns true if the texture was created; false otherwise.
+
+ \sa destroy(), textureId()
+*/
+bool QCLTexture2D::create(QCLContextGL *context, const QSize &size)
+{
+ Q_D(QCLTexture2D);
+ Q_ASSERT(context && size.width() > 0 && size.height() > 0);
+ Q_ASSERT(memoryId() == 0); // Must not be created already.
+ d->clContext = context;
+
+ // Create the texture in the GL context.
+ GLuint textureId;
+ glGenTextures(1, &textureId);
+ glBindTexture(GL_TEXTURE_2D, textureId);
+#ifdef GL_CLAMP_TO_EDGE
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+#else
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
+#endif
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size.width(), size.height(), 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, 0);
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+ // If the context supports object sharing, then this is really easy.
+ if (context->supportsObjectSharing()) {
+ QCLImage2D image = context->createTexture2D
+ (GL_TEXTURE_2D, textureId, 0, QCL::WriteOnly);
+ if (image.isNull()) {
+ glDeleteTextures(1, &textureId);
+ return false;
+ }
+ d->setContextAndId(QGLContext::currentContext(), textureId);
+ setId(image.context(), image.memoryId());
+ d->size = size;
+ d->directRender = true;
+ return true;
+ }
+
+#ifdef USE_PIXEL_UNPACK_BUFFERS
+ // Create a pixel unpack buffer for downloading image data
+ // out of OpenCL and uploading it into OpenGL.
+ d->pixelBuffer = new QGLBuffer(QGLBuffer::PixelUnpackBuffer);
+ d->pixelBuffer->setUsagePattern(QGLBuffer::DynamicDraw);
+ if (d->pixelBuffer->create()) {
+ d->pixelBuffer->bind();
+ d->pixelBuffer->allocate(size.width() * size.height() * 4);
+ d->pixelBuffer->release();
+ } else {
+ delete d->pixelBuffer;
+ d->pixelBuffer = 0;
+ }
+#endif
+
+ // Create a 2D image in the OpenCL device for rendering with OpenCL.
+ QCLImage2D image = context->createImage2DDevice
+ (QCLImageFormat(QCLImageFormat::Order_RGBA,
+ QCLImageFormat::Type_Normalized_UInt8),
+ size, QCL::WriteOnly);
+ if (image.isNull()) {
+ glDeleteTextures(1, &textureId);
+#ifdef USE_PIXEL_UNPACK_BUFFERS
+ delete d->pixelBuffer;
+ d->pixelBuffer = 0;
+#endif
+ return false;
+ }
+ d->setContextAndId(QGLContext::currentContext(), textureId);
+ setId(image.context(), image.memoryId());
+ d->size = size;
+ d->directRender = false;
+ return true;
+}
+
+/*!
+ \fn bool QCLTexture2D::create(QCLContextGL *context, int width, int height)
+ \overload
+
+ Constructs an OpenCL texture of size (\a width, \a height)
+ in \a context. Returns true if the texture was created; false otherwise.
+
+ \sa destroy()
+*/
+
+/*!
+ Destroys this OpenCL texture object.
+*/
+void QCLTexture2D::destroy()
+{
+ Q_D(QCLTexture2D);
+ setId(0, 0);
+ GLuint textureId = d->textureId;
+ if (textureId) {
+ QGLContext *oldContext;
+ QGLContext *currentContext = const_cast<QGLContext *>(QGLContext::currentContext());
+ if (currentContext != d->context && !QGLContext::areSharing(d->context, currentContext)) {
+ oldContext = currentContext;
+ const_cast<QGLContext *>(d->context)->makeCurrent();
+ } else {
+ oldContext = 0;
+ }
+ glDeleteTextures(1, &textureId);
+ if (oldContext)
+ oldContext->makeCurrent();
+ }
+#ifdef USE_PIXEL_UNPACK_BUFFERS
+ delete d->pixelBuffer;
+ d->pixelBuffer = 0;
+#endif
+ d->context = 0;
+ d->textureId = 0;
+ d->size = QSize();
+ d->directRender = false;
+}
+
+/*!
+ Acquires access to this texture so that OpenCL kernels
+ can render into it. OpenGL cannot use the texture until
+ release() is called.
+
+ \sa release()
+*/
+void QCLTexture2D::acquire()
+{
+ Q_D(QCLTexture2D);
+ if (d->directRender)
+ d->clContext->acquire(*this).waitForFinished();
+}
+
+/*!
+ Releases access to this texture so that OpenGL can use it again.
+ The textureId() will also be bound to the current OpenGL context.
+
+ \sa acquire()
+*/
+void QCLTexture2D::release()
+{
+ Q_D(QCLTexture2D);
+ if (!d->textureId)
+ return;
+
+ // If we are doing direct rendering, then just release the OpenCL object.
+ if (d->directRender) {
+ d->clContext->release(*this).waitForFinished();
+ glBindTexture(GL_TEXTURE_2D, d->textureId);
+ return;
+ }
+
+ // Wait for the current OpenCL commands to finish.
+ context()->marker().waitForFinished();
+
+ // Upload the contents of the OpenCL buffer into the texture.
+ void *ptr;
+#ifdef USE_PIXEL_UNPACK_BUFFERS
+ if (d->pixelBuffer) {
+ d->pixelBuffer->bind();
+ ptr = d->pixelBuffer->map(QGLBuffer::ReadWrite);
+ if (ptr) {
+ read(ptr, QRect(QPoint(0, 0), d->size), d->size.width() * 4);
+ d->pixelBuffer->unmap();
+ glBindTexture(GL_TEXTURE_2D, d->textureId);
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0,
+ d->size.width(), d->size.height(),
+ GL_RGBA, GL_UNSIGNED_BYTE, 0);
+ d->pixelBuffer->release();
+ return;
+ }
+ // Pixel buffer cannot be mapped, so it is of no use to us.
+ d->pixelBuffer->release();
+ delete d->pixelBuffer;
+ d->pixelBuffer = 0;
+ }
+#endif
+ ptr = map(QRect(QPoint(0, 0), d->size), QCL::ReadOnly);
+ glBindTexture(GL_TEXTURE_2D, d->textureId);
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0,
+ d->size.width(), d->size.height(),
+ GL_RGBA, GL_UNSIGNED_BYTE, ptr);
+ unmap(ptr);
+}
+
+/*!
+ Returns the OpenGL texture identifier for this OpenCL texture object.
+*/
+GLuint QCLTexture2D::textureId() const
+{
+ Q_D(const QCLTexture2D);
+ return d->textureId;
+}
+
+QT_END_NAMESPACE
+
+#include "qcltexture2d.moc"
diff --git a/src/openclgl/qcltexture2d.h b/src/openclgl/qcltexture2d.h
new file mode 100644
index 0000000..5d4f930
--- /dev/null
+++ b/src/openclgl/qcltexture2d.h
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtOpenCL module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QCLTEXTURE2D_H
+#define QCLTEXTURE2D_H
+
+#include "qclimage.h"
+#include <QtCore/qscopedpointer.h>
+#include <QtOpenGL/qgl.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(CL)
+
+class QCLContextGL;
+class QCLTexture2DPrivate;
+
+// Note: this class probably should be in the QtOpenGL library.
+class Q_CLGL_EXPORT QCLTexture2D : public QCLImage2D
+{
+public:
+ QCLTexture2D();
+ ~QCLTexture2D();
+
+ bool create(QCLContextGL *context, const QSize &size);
+ bool create(QCLContextGL *context, int width, int height);
+ void destroy();
+
+ void acquire();
+ void release();
+
+ GLuint textureId() const;
+
+private:
+ QScopedPointer<QCLTexture2DPrivate> d_ptr;
+
+ Q_DISABLE_COPY(QCLTexture2D)
+ Q_DECLARE_PRIVATE(QCLTexture2D)
+};
+
+inline bool QCLTexture2D::create(QCLContextGL *context, int width, int height)
+{
+ return create(context, QSize(width, height));
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif