diff options
author | Rhys Weatherley <rhys.weatherley@nokia.com> | 2010-02-15 08:22:46 +1000 |
---|---|---|
committer | Rhys Weatherley <rhys.weatherley@nokia.com> | 2010-02-15 09:23:15 +1000 |
commit | bfaac138e3278b1d9ab998ce68ee7f48b8723b84 (patch) | |
tree | 5f35d7b67f5fe136c614bf5715dea29ad17ac462 /examples | |
parent | 7406cd34b6b2ef17b2d6c232779b9e7750599197 (diff) |
Add a Mandelbrot viewer example for the OpenCL library.
Diffstat (limited to 'examples')
-rw-r--r-- | examples/opencl/mandelbrot/image.cpp | 98 | ||||
-rw-r--r-- | examples/opencl/mandelbrot/image.h | 87 | ||||
-rw-r--r-- | examples/opencl/mandelbrot/imagecl.cpp | 147 | ||||
-rw-r--r-- | examples/opencl/mandelbrot/imagecl.h | 68 | ||||
-rw-r--r-- | examples/opencl/mandelbrot/imagenative.cpp | 147 | ||||
-rw-r--r-- | examples/opencl/mandelbrot/imagenative.h | 64 | ||||
-rw-r--r-- | examples/opencl/mandelbrot/main.cpp | 52 | ||||
-rw-r--r-- | examples/opencl/mandelbrot/mandelbrot.cl | 100 | ||||
-rw-r--r-- | examples/opencl/mandelbrot/mandelbrot.pro | 25 | ||||
-rw-r--r-- | examples/opencl/mandelbrot/mandelbrot.qrc | 5 | ||||
-rw-r--r-- | examples/opencl/mandelbrot/palette.cpp | 156 | ||||
-rw-r--r-- | examples/opencl/mandelbrot/palette.h | 90 | ||||
-rw-r--r-- | examples/opencl/mandelbrot/view.cpp | 101 | ||||
-rw-r--r-- | examples/opencl/mandelbrot/view.h | 70 | ||||
-rw-r--r-- | examples/opencl/opencl.pro | 2 |
15 files changed, 1211 insertions, 1 deletions
diff --git a/examples/opencl/mandelbrot/image.cpp b/examples/opencl/mandelbrot/image.cpp new file mode 100644 index 0000000..9483f30 --- /dev/null +++ b/examples/opencl/mandelbrot/image.cpp @@ -0,0 +1,98 @@ +/**************************************************************************** +** +** 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 Qt3D 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 "image.h" +#include "imagenative.h" +#include "imagecl.h" +#include "palette.h" +#include <QtCore/qdatetime.h> +#include <QtCore/qdebug.h> + +Image::Image(int width, int height) + : img(width, height, QImage::Format_RGB32) + , regionChanged(true) + , lastIterations(-1) +{ + setRegion(-0.7f, 0.0f, 3.0769f); +} + +Image::~Image() +{ +} + +// Set a region based on its center and diameter in the x direction. +void Image::setRegion(qreal centerx, qreal centery, qreal diameterx) +{ + qreal diametery = diameterx * img.height() / img.width(); + rgn = QRectF(centerx - diameterx * 0.5f, + centery - diametery * 0.5f, + diameterx, diametery); + regionChanged = true; +} + +Image *Image::createImage(int width, int height) +{ + if (ImageCL::hasOpenCL()) + return new ImageCL(width, height); + else + return new ImageNative(width, height); +} + +void Image::generate(int maxIterations, const Palette& palette) +{ + Q_ASSERT(maxIterations <= 65535); + + // If the parameters have changed, then regenerate the index data. + if (regionChanged || maxIterations != lastIterations) { + QTime time; + time.start(); + generateIterationData(maxIterations, rgn); + regionChanged = false; + lastIterations = maxIterations; + qDebug() << "Mandelbrot:" << rgn + << "iterations =" << maxIterations + << "elapsed =" << time.elapsed() << "ms"; + } + + // Colorize the index data to create the final image. + QVector<QRgb> colors = palette.createTable(maxIterations); + generateImage(&img, maxIterations, colors.constData()); +} diff --git a/examples/opencl/mandelbrot/image.h b/examples/opencl/mandelbrot/image.h new file mode 100644 index 0000000..546c9bc --- /dev/null +++ b/examples/opencl/mandelbrot/image.h @@ -0,0 +1,87 @@ +/**************************************************************************** +** +** 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 Qt3D 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 IMAGE_H +#define IMAGE_H + +#include <QtGui/qimage.h> +#include <QtCore/qmetatype.h> + +class Palette; + +class Image +{ +public: + Image(int width, int height); + virtual ~Image(); + + // QMetaType::Float for 32-bit IEEE precision. + // QMetaType::Double for 64-bit IEEE precision. + // QMetaType::User for arbitrary precision. + virtual QMetaType::Type precision() const = 0; + + QImage image() const { return img; } + + QRectF region() const { return rgn; } + void setRegion(const QRectF& value) + { rgn = value; regionChanged = true; } + void setRegion(qreal centerx, qreal centery, qreal diameterx); + + void forceUpdate() { regionChanged = true; } + + void generate(int maxIterations, const Palette& palette); + + static Image *createImage(int width, int height); + +protected: + virtual void generateIterationData + (int maxIterations, const QRectF& region) = 0; + virtual void generateImage + (QImage *image, int maxIterations, const QRgb *colors) = 0; + +private: + QImage img; + QRectF rgn; + bool regionChanged; + int lastIterations; +}; + +#endif diff --git a/examples/opencl/mandelbrot/imagecl.cpp b/examples/opencl/mandelbrot/imagecl.cpp new file mode 100644 index 0000000..b55981f --- /dev/null +++ b/examples/opencl/mandelbrot/imagecl.cpp @@ -0,0 +1,147 @@ +/**************************************************************************** +** +** 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 Qt3D 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 "imagecl.h" +#include <QtCore/qvarlengtharray.h> +#include <QtGui/qcolor.h> + +class ImageCLContext +{ +public: + ImageCLContext(); + ~ImageCLContext(); + + QCLContext *context; + QCLProgram program; + QCLKernel mandelbrot; + QCLKernel colorize; +}; + +ImageCLContext::ImageCLContext() +{ + context = new QCLContext(); + if (!context->create()) + return; + + program = context->buildProgramFromSourceFile + (QLatin1String(":/mandelbrot.cl")); + mandelbrot = program.createKernel("mandelbrot"); + colorize = program.createKernel("colorize"); +} + +ImageCLContext::~ImageCLContext() +{ + delete context; +} + +Q_GLOBAL_STATIC(ImageCLContext, image_context) + +ImageCL::ImageCL(int width, int height) + : Image(width, height) + , wid(width), ht(height) +{ + // Create an OpenCL buffer to hold the raw iteration count data. + // The buffer lives on the OpenCL device and does not need to + // be accessed by the host. + ImageCLContext *ctx = image_context(); + data = ctx->context->createBufferDevice + (width * height * sizeof(uint), QCLBuffer::ReadWrite); +} + +ImageCL::~ImageCL() +{ +} + +QMetaType::Type ImageCL::precision() const +{ + return QMetaType::Float; +} + +bool ImageCL::hasOpenCL() +{ + ImageCLContext *ctx = image_context(); + return ctx->context->isCreated(); +} + +void ImageCL::generateIterationData + (int maxIterations, const QRectF& region) +{ + ImageCLContext *ctx = image_context(); + QCLKernel mandelbrot = ctx->mandelbrot; + + mandelbrot.setGlobalWorkSize(QCLWorkSize(wid, ht)); + QCLEvent event = mandelbrot + (data, float(region.x()), float(region.y()), + float(region.width()), float(region.height()), + wid, ht, maxIterations); + event.wait(); +} + +void ImageCL::generateImage + (QImage *image, int maxIterations, const QRgb *colors) +{ + ImageCLContext *ctx = image_context(); + QCLKernel colorize = ctx->colorize; + + // Upload the color table into a buffer in the device. + QCLBuffer colorBuffer = ctx->context->createBufferDevice + (maxIterations * sizeof(float) * 4, QCLBuffer::ReadOnly); + QVarLengthArray<float> floatColors; + for (int index = 0; index < maxIterations; ++index) { + QColor color(colors[index]); + floatColors.append(float(color.redF())); + floatColors.append(float(color.greenF())); + floatColors.append(float(color.blueF())); + floatColors.append(float(color.alphaF())); + } + colorBuffer.write(0, floatColors.constData(), + maxIterations * sizeof(float) * 4); + + // Map the image so that both the device and the host can access it. + QCLImage2D imageBuffer = ctx->context->createImage2DHost + (image, QCLBuffer::WriteOnly); + + // Execute the "colorize" kernel. + colorize.setGlobalWorkSize(QCLWorkSize(wid, ht)); + QCLEvent event = colorize + (data, imageBuffer, colorBuffer, wid, maxIterations); + event.wait(); +} diff --git a/examples/opencl/mandelbrot/imagecl.h b/examples/opencl/mandelbrot/imagecl.h new file mode 100644 index 0000000..78adf1e --- /dev/null +++ b/examples/opencl/mandelbrot/imagecl.h @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** 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 Qt3D 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 IMAGECL_H +#define IMAGECL_H + +#include "image.h" +#include "qclcontext.h" + +class ImageCL : public Image +{ +public: + ImageCL(int width, int height); + virtual ~ImageCL(); + + virtual QMetaType::Type precision() const; + + static bool hasOpenCL(); + +protected: + int wid, ht; + QCLBuffer data; + + void generateIterationData + (int maxIterations, const QRectF& region); + void generateImage + (QImage *image, int maxIterations, const QRgb *colors); +}; + +#endif diff --git a/examples/opencl/mandelbrot/imagenative.cpp b/examples/opencl/mandelbrot/imagenative.cpp new file mode 100644 index 0000000..524d695 --- /dev/null +++ b/examples/opencl/mandelbrot/imagenative.cpp @@ -0,0 +1,147 @@ +/**************************************************************************** +** +** 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 Qt3D 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 "imagenative.h" +#include <QtCore/qmath.h> + +// Define the floating-point precision to use for calculations. +//typedef double mreal; +typedef float mreal; + +ImageNative::ImageNative(int width, int height) + : Image(width, height) + , data(width, height, QImage::Format_RGB32) +{ +} + +ImageNative::~ImageNative() +{ +} + +// QMetaType::Float for 32-bit IEEE precision. +// QMetaType::Double for 64-bit IEEE precision. +// QMetaType::User for arbitrary precision. +QMetaType::Type ImageNative::precision() const +{ + if (sizeof(mreal) == sizeof(float)) + return QMetaType::Float; + else + return QMetaType::Double; +} + +// Algorithm from: http://en.wikipedia.org/wiki/Mandelbrot_set +// This generates uint values for each pixel. The top 16 bits +// contain the iteration count, and the bottom 16 bits contains +// an interpolation value for creating gradients between colors. +void ImageNative::generateIterationData + (int maxIterations, const QRectF& region) +{ + int width = data.width(); + int height = data.height(); + mreal xstep = region.width() / width; + mreal ystep = region.height() / height; + mreal yin = region.y(); + uint *line = reinterpret_cast<uint *>(data.bits()); + int stride = data.bytesPerLine() / sizeof(uint); + line += stride * (height - 1); // flip y axis so y = 1 is at top. + mreal loglogb = log(log(2.0)); + mreal invlog2 = 1.0 / log(2.0); + for (int ypos = 0; ypos < height; ++ypos, yin += ystep) { + mreal xin = region.x(); + for (int xpos = 0; xpos < width; ++xpos, xin += xstep) { + // Find the color to use with the "escape time" algorithm. + int iteration = 0; + mreal x = 0; + mreal y = 0; + while (iteration < maxIterations) { + mreal x2 = x * x; + mreal y2 = y * y; + if ((x2 + y2) > (2.0f * 2.0f)) + break; + mreal xtemp = x2 - y2 + xin; + y = 2 * x * y + yin; + x = xtemp; + ++iteration; + } + if (iteration < (maxIterations - 1)) { + // Use the Normalized Iteration Count Algorithm + // to compute an interpolation value between two + // adjacent colors for a continuous tone image. + // From: http://math.unipa.it/~grim/Jbarrallo.PDF + mreal v = (loglogb - log(log(sqrt(x * x + y * y)))) * invlog2; + int fraction = int(v * 65535.0f); + line[xpos] = (iteration << 16) + fraction; + } else { + line[xpos] = (iteration << 16); + } + } + line -= stride; + } +} + +void ImageNative::generateImage + (QImage *image, int maxIterations, const QRgb *colors) +{ + QRgb *dst = reinterpret_cast<uint *>(image->bits()); + const uint *src = reinterpret_cast<uint *>(data.bits()); + uint count = image->width() * image->height(); + while (count-- > 0) { + int iteration = (src[0] >> 16); + if (iteration < (maxIterations - 1)) { + qreal v = (src[0] & 0xFFFF) / 65535.0f; + QRgb color1 = colors[iteration]; + QRgb color2 = colors[iteration + 1]; + int red = int((qRed(color2) - qRed(color1)) * v) + + qRed(color1); + int green = int((qGreen(color2) - qGreen(color1)) * v) + + qGreen(color1); + int blue = int((qBlue(color2) - qBlue(color1)) * v) + + qBlue(color1); + dst[0] = qRgb(red, green, blue); + } else if (iteration < maxIterations) { + dst[0] = colors[iteration]; + } else { + dst[0] = qRgb(0, 0, 0); + } + ++src; + ++dst; + } +} diff --git a/examples/opencl/mandelbrot/imagenative.h b/examples/opencl/mandelbrot/imagenative.h new file mode 100644 index 0000000..59dd3d4 --- /dev/null +++ b/examples/opencl/mandelbrot/imagenative.h @@ -0,0 +1,64 @@ +/**************************************************************************** +** +** 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 Qt3D 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 IMAGENATIVE_H +#define IMAGENATIVE_H + +#include "image.h" + +class ImageNative : public Image +{ +public: + ImageNative(int width, int height); + virtual ~ImageNative(); + + virtual QMetaType::Type precision() const; + +protected: + QImage data; + + void generateIterationData + (int maxIterations, const QRectF& region); + void generateImage + (QImage *image, int maxIterations, const QRgb *colors); +}; + +#endif diff --git a/examples/opencl/mandelbrot/main.cpp b/examples/opencl/mandelbrot/main.cpp new file mode 100644 index 0000000..fc557bd --- /dev/null +++ b/examples/opencl/mandelbrot/main.cpp @@ -0,0 +1,52 @@ +/**************************************************************************** +** +** 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 Qt3D 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 <QApplication> +#include <QDebug> +#include "view.h" + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + View view; + view.show(); + return app.exec(); +} diff --git a/examples/opencl/mandelbrot/mandelbrot.cl b/examples/opencl/mandelbrot/mandelbrot.cl new file mode 100644 index 0000000..4c43b17 --- /dev/null +++ b/examples/opencl/mandelbrot/mandelbrot.cl @@ -0,0 +1,100 @@ +/**************************************************************************** +** +** 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 Qt3D 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$ +** +****************************************************************************/ + +__kernel void mandelbrot(__global __write_only int *data, + const float regionx, const float regiony, + const float regionwidth, const float regionheight, + const int pixelwidth, const int pixelheight, + const int maxIterations) +{ + int xpixel = get_global_id(0); + int ypixel = get_global_id(1); + float xin = regionx + xpixel * regionwidth / pixelwidth; + float yin = regiony + ypixel * regionheight / pixelheight; + int iteration = 0; + float x = 0; + float y = 0; + while (iteration < maxIterations) { + float x2 = x * x; + float y2 = y * y; + if ((x2 + y2) > 4.0) + break; + float xtemp = x2 - y2 + xin; + y = 2 * x * y + yin; + x = xtemp; + ++iteration; + } + int pos = ypixel * pixelwidth + xpixel; + if (iteration < (maxIterations - 1)) { + // Use the Normalized Iteration Count Algorithm + // to compute an interpolation value between two + // adjacent colors for a continuous tone image. + // From: http://math.unipa.it/~grim/Jbarrallo.PDF + const float loglogb = log(log(2.0f)); + const float invlog2 = 1.0f / log(2.0f); + float v = (loglogb - log(log(sqrt(x * x + y * y)))) * invlog2; + int fraction = (int)(v * 65535.0f); + data[pos] = (iteration << 16) + fraction; + } else { + data[pos] = (iteration << 16); + } +} + +__kernel void colorize(__global __read_only int *data, + __write_only image2d_t image, + __global __read_only float4 *colors, + const int pixelwidth, + const int maxIterations) +{ + int xpixel = get_global_id(0); + int ypixel = get_global_id(1); + int pos = ypixel * pixelwidth + xpixel; + int iteration = (data[pos] >> 16); + if (iteration < (maxIterations - 1)) { + float v = (data[pos] & 0xFFFF) / 65535.0f; + float4 color = mix(colors[iteration], colors[iteration + 1], v); + write_imagef(image, (int2)(xpixel, ypixel), color); + } else if (iteration < maxIterations) { + write_imagef(image, (int2)(xpixel, ypixel), colors[iteration]); + } else { + write_imagef(image, (int2)(xpixel, ypixel), (float4)(0, 0, 0, 1)); + } +} diff --git a/examples/opencl/mandelbrot/mandelbrot.pro b/examples/opencl/mandelbrot/mandelbrot.pro new file mode 100644 index 0000000..91a0a52 --- /dev/null +++ b/examples/opencl/mandelbrot/mandelbrot.pro @@ -0,0 +1,25 @@ +###################################################################### +# Automatically generated by qmake (2.01a) Sat Feb 13 10:16:42 2010 +###################################################################### + +TEMPLATE = app +TARGET = mandelbrot +DEPENDPATH += . +INCLUDEPATH += . + +# Input +SOURCES += main.cpp \ + palette.cpp \ + image.cpp \ + imagecl.cpp \ + imagenative.cpp \ + view.cpp +HEADERS += palette.h \ + image.h \ + imagecl.h \ + imagenative.h \ + view.h +RESOURCES += mandelbrot.qrc + +LIBS += -L../../../lib -L../../../bin +include(../../../src/opencl/opencl_dep.pri) diff --git a/examples/opencl/mandelbrot/mandelbrot.qrc b/examples/opencl/mandelbrot/mandelbrot.qrc new file mode 100644 index 0000000..e9d7ab1 --- /dev/null +++ b/examples/opencl/mandelbrot/mandelbrot.qrc @@ -0,0 +1,5 @@ +<!DOCTYPE RCC><RCC version="1.0"> +<qresource> + <file>mandelbrot.cl</file> +</qresource> +</RCC> diff --git a/examples/opencl/mandelbrot/palette.cpp b/examples/opencl/mandelbrot/palette.cpp new file mode 100644 index 0000000..555f5ea --- /dev/null +++ b/examples/opencl/mandelbrot/palette.cpp @@ -0,0 +1,156 @@ +/**************************************************************************** +** +** 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 Qt3D 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 "palette.h" + +Palette::Palette() + : type(QColor::Invalid), offset(0.0f) +{ + setStandardPalette(Fire); +} + +Palette::~Palette() +{ +} + +void Palette::setStandardPalette(StandardPalette palette) +{ + clear(); + switch (palette) { + default: case Red: + addHsv(0.0f, 0.0f, 1.0f, 1.0f); + addHsv(1.0f, 1.0f, 1.0f, 1.0f); + break; + case Blue: + addHsv(0.0f, 0.65f, 1.0f, 0.5f); + addHsv(1.0f, 0.05f, 1.0f, 1.0f); + break; + + // The following palettes are from xMandelbrotViewer. + // http://math.hws.edu/xJava/MB/ + case EarthSky: + addRgb(0.0f, 1.0f, 1.0f, 1.0f); + addRgb(0.15f, 1.0f, 0.8f, 0.0f); + addRgb(0.33f, 0.53f, 0.12f, 0.075f); + addRgb(0.67f, 0.0f, 0.0f, 0.6f); + addRgb(0.85f, 0.0f, 0.4f, 1.0f); + addRgb(1.0f, 1.0f, 1.0f, 1.0f); + setOffset(0.85f); + break; + case HotCold: + addRgb(0.0f, 1.0f, 1.0f, 1.0f); + addRgb(0.16f, 0.0f, 0.4f, 1.0f); + addRgb(0.5f, 0.2f, 0.2f, 0.2f); + addRgb(0.84f, 1.0f, 0.0f, 0.8f); + addRgb(1.0f, 1.0f, 1.0f, 1.0f); + break; + case Fire: + addRgb(0.0f, 0.0f, 0.0f, 0.0f); + addRgb(0.17f, 1.0f, 0.0f, 0.0f); + addRgb(0.83f, 1.0f, 1.0f, 0.0f); + addRgb(1.0f, 1.0f, 1.0f, 1.0f); + break; + } +} + +void Palette::clear() +{ + type = QColor::Invalid; + offset = 0.0f; + ranges.clear(); +} + +void Palette::addRgb(qreal start, qreal r, qreal g, qreal b) +{ + type = QColor::Rgb; + Range range; + range.start = start; + range.r = r; + range.g = g; + range.b = b; + ranges.append(range); +} + +void Palette::addHsv(qreal start, qreal h, qreal s, qreal v) +{ + type = QColor::Hsv; + Range range; + range.start = start; + range.h = h; + range.s = s; + range.v = v; + ranges.append(range); +} + +QVector<QRgb> Palette::createTable(int size) const +{ + Q_ASSERT(ranges.size() >= 2); + Q_ASSERT(ranges[ranges.size() - 1].start == 1.0f); + QVector<QRgb> colors; + colors.resize(size); + int ioffset = int(offset * size); + for (int index = 0; index < size; ++index) { + qreal amt = qreal((index + ioffset) % size) / (size - 1); + int posn = 1; + while (ranges[posn].start < 1.0f && ranges[posn].start < amt) + ++posn; + amt = (amt - ranges[posn - 1].start) / + (ranges[posn].start - ranges[posn - 1].start); + if (type == QColor::Rgb) { + qreal r = ranges[posn - 1].r + + (ranges[posn].r - ranges[posn - 1].r) * amt; + qreal g = ranges[posn - 1].g + + (ranges[posn].g - ranges[posn - 1].g) * amt; + qreal b = ranges[posn - 1].b + + (ranges[posn].b - ranges[posn - 1].b) * amt; + colors[index] = QColor::fromRgbF(r, g, b).rgb(); + } else { + qreal h = ranges[posn - 1].h + + (ranges[posn].h - ranges[posn - 1].h) * amt; + qreal s = ranges[posn - 1].s + + (ranges[posn].s - ranges[posn - 1].s) * amt; + qreal v = ranges[posn - 1].v + + (ranges[posn].v - ranges[posn - 1].v) * amt; + colors[index] = QColor::fromHsvF(h, s, v).rgb(); + } + } + return colors; +} diff --git a/examples/opencl/mandelbrot/palette.h b/examples/opencl/mandelbrot/palette.h new file mode 100644 index 0000000..dc19a16 --- /dev/null +++ b/examples/opencl/mandelbrot/palette.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 Qt3D 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 PALETTE_H +#define PALETTE_H + +#include <QtCore/qvector.h> +#include <QtGui/qcolor.h> + +class Palette +{ +public: + Palette(); + ~Palette(); + + enum StandardPalette + { + Red, + Blue, + EarthSky, + HotCold, + Fire + }; + + void setStandardPalette(StandardPalette palette); + + void clear(); + void addRgb(qreal start, qreal r, qreal g, qreal b); + void addHsv(qreal start, qreal h, qreal s, qreal v); + void setOffset(qreal value) { offset = value; } + + QVector<QRgb> createTable(int size) const; + +private: + struct Range + { + qreal start; + union { + struct { + qreal r, g, b; + }; + struct { + qreal h, s, v; + }; + }; + }; + QColor::Spec type; + qreal offset; + QVector<Range> ranges; +}; + +#endif diff --git a/examples/opencl/mandelbrot/view.cpp b/examples/opencl/mandelbrot/view.cpp new file mode 100644 index 0000000..71559e2 --- /dev/null +++ b/examples/opencl/mandelbrot/view.cpp @@ -0,0 +1,101 @@ +/**************************************************************************** +** +** 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 Qt3D 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 "view.h" +#include "image.h" +#include "palette.h" +#include <QtGui/qpainter.h> +#include <QtCore/qtimer.h> + +View::View(QWidget *parent) + : QWidget(parent) +{ + setMinimumSize(768, 512); + setMaximumSize(768, 512); + + palette = new Palette(); + palette->setStandardPalette(Palette::Blue); + offset = 0.0f; + step = 0.05f; + + image = Image::createImage(768, 512); + image->generate(200, *palette); + + QTimer *timer = new QTimer(this); + connect(timer, SIGNAL(timeout()), this, SLOT(animate())); + timer->start(50); +} + +View::~View() +{ + delete palette; + delete image; +} + +void View::paintEvent(QPaintEvent *) +{ + QPainter painter(this); + QImage img = image->image(); + painter.drawImage((width() - img.width()) / 2, + (height() - img.height()) / 2, + img); +} + +void View::animate() +{ + if (step > 0) { + offset += step; + if (offset >= 1.0f) { + offset = 1.0f; + step = -step; + } + } else { + offset += step; + if (offset <= 0.0f) { + offset = 0.0f; + step = -step; + } + } + palette->setOffset(offset); + //image->forceUpdate(); + image->generate(200, *palette); + update(); +} diff --git a/examples/opencl/mandelbrot/view.h b/examples/opencl/mandelbrot/view.h new file mode 100644 index 0000000..cbf453b --- /dev/null +++ b/examples/opencl/mandelbrot/view.h @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** 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 Qt3D 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 VIEW_H +#define VIEW_H + +#include <QtGui/qwidget.h> + +class Image; +class Palette; + +class View : public QWidget +{ + Q_OBJECT +public: + View(QWidget *parent = 0); + ~View(); + +private slots: + void animate(); + +protected: + void paintEvent(QPaintEvent *); + +private: + Image *image; + Palette *palette; + qreal offset; + qreal step; +}; + +#endif diff --git a/examples/opencl/opencl.pro b/examples/opencl/opencl.pro index 0be1dc9..557c348 100644 --- a/examples/opencl/opencl.pro +++ b/examples/opencl/opencl.pro @@ -1,2 +1,2 @@ TEMPLATE = subdirs -SUBDIRS = vectoradd +SUBDIRS = vectoradd mandelbrot |