Warning, /graphics/krita/3rdparty/ext_qt/0007-Implement-a-manual-test-for-checking-is-HDR-features.patch is written in an unsupported language. File is not indexed.

0001 From 8c5e4fec56124e22f05881ffa6e6127428d5ee1b Mon Sep 17 00:00:00 2001
0002 From: Dmitry Kazakov <dimula73@gmail.com>
0003 Date: Sun, 10 Feb 2019 22:55:59 +0300
0004 Subject: [PATCH 17/47] Implement a manual test for checking is HDR features
0005  work
0006 
0007 Test plan:
0008 
0009 1) Run without arguments: `hdr-openglwidget.exe`
0010    It should show you three rectangles: the left one should be HDR'ly
0011    bright, the other ones should be SDR'ly dim and look exactly the same.
0012 
0013 3) Run in Bt. 2020 PQ mode: `hdr-openglwidget.exe --bt2020pq`
0014    The result should look exactly the same.
0015 
0016 4) Run in SDR sRGB mode: `hdr-openglwidget.exe --srgb`.
0017    All three images should look SDR'ly dim.
0018 
0019 NOTE:
0020 Please note that the current implementation of SDR compositing
0021 in QOpenGLTextureBlitter doesn't support user configuration for
0022 SDR brightness from the system. This API is available for UWP
0023 applications only. It means that when changing "SDR brightness"
0024 slider in Windows' settings, the brightness of our SDR widget
0025 will not change. More that that, it might even be different from
0026 the brightness of other SDR applications.
0027 
0028 Change-Id: Idccc790937c9061ec618ab21f6b71bd0620cd2cc
0029 ---
0030  .../hdr-qopenglwidget/KisGLImageF16.cpp       | 131 +++++++++
0031  .../manual/hdr-qopenglwidget/KisGLImageF16.h  |  68 +++++
0032  .../hdr-qopenglwidget/KisGLImageWidget.cpp    | 252 ++++++++++++++++++
0033  .../hdr-qopenglwidget/KisGLImageWidget.h      |  77 ++++++
0034  .../hdr-qopenglwidget/hdr-openglwidget.pro    |  20 ++
0035  .../kis_gl_image_widget.frag                  |  23 ++
0036  .../hdr-qopenglwidget/kis_gl_image_widget.qrc |   6 +
0037  .../kis_gl_image_widget.vert                  |  17 ++
0038  tests/manual/hdr-qopenglwidget/main.cpp       | 153 +++++++++++
0039  .../hdr-qopenglwidget/openglprobeutils.cpp    | 139 ++++++++++
0040  .../hdr-qopenglwidget/openglprobeutils.h      |  42 +++
0041  tests/manual/hdr-qopenglwidget/window.cpp     | 219 +++++++++++++++
0042  tests/manual/hdr-qopenglwidget/window.h       |  69 +++++
0043  tests/manual/manual.pro                       |   2 +-
0044  14 files changed, 1217 insertions(+), 1 deletion(-)
0045  create mode 100644 tests/manual/hdr-qopenglwidget/KisGLImageF16.cpp
0046  create mode 100644 tests/manual/hdr-qopenglwidget/KisGLImageF16.h
0047  create mode 100644 tests/manual/hdr-qopenglwidget/KisGLImageWidget.cpp
0048  create mode 100644 tests/manual/hdr-qopenglwidget/KisGLImageWidget.h
0049  create mode 100644 tests/manual/hdr-qopenglwidget/hdr-openglwidget.pro
0050  create mode 100644 tests/manual/hdr-qopenglwidget/kis_gl_image_widget.frag
0051  create mode 100644 tests/manual/hdr-qopenglwidget/kis_gl_image_widget.qrc
0052  create mode 100644 tests/manual/hdr-qopenglwidget/kis_gl_image_widget.vert
0053  create mode 100644 tests/manual/hdr-qopenglwidget/main.cpp
0054  create mode 100644 tests/manual/hdr-qopenglwidget/openglprobeutils.cpp
0055  create mode 100644 tests/manual/hdr-qopenglwidget/openglprobeutils.h
0056  create mode 100644 tests/manual/hdr-qopenglwidget/window.cpp
0057  create mode 100644 tests/manual/hdr-qopenglwidget/window.h
0058 
0059 diff --git a/tests/manual/hdr-qopenglwidget/KisGLImageF16.cpp b/tests/manual/hdr-qopenglwidget/KisGLImageF16.cpp
0060 new file mode 100644
0061 index 0000000000..a84b676f5b
0062 --- /dev/null
0063 +++ b/tests/manual/hdr-qopenglwidget/KisGLImageF16.cpp
0064 @@ -0,0 +1,131 @@
0065 +/****************************************************************************
0066 +**
0067 +** Copyright (C) 2019 The Qt Company Ltd.
0068 +** Contact: https://www.qt.io/licensing/
0069 +**
0070 +** This file is part of the test suite of the Qt Toolkit.
0071 +**
0072 +** $QT_BEGIN_LICENSE:GPL-EXCEPT$
0073 +** Commercial License Usage
0074 +** Licensees holding valid commercial Qt licenses may use this file in
0075 +** accordance with the commercial license agreement provided with the
0076 +** Software or, alternatively, in accordance with the terms contained in
0077 +** a written agreement between you and The Qt Company. For licensing terms
0078 +** and conditions see https://www.qt.io/terms-conditions. For further
0079 +** information use the contact form at https://www.qt.io/contact-us.
0080 +**
0081 +** GNU General Public License Usage
0082 +** Alternatively, this file may be used under the terms of the GNU
0083 +** General Public License version 3 as published by the Free Software
0084 +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
0085 +** included in the packaging of this file. Please review the following
0086 +** information to ensure the GNU General Public License requirements will
0087 +** be met: https://www.gnu.org/licenses/gpl-3.0.html.
0088 +**
0089 +** $QT_END_LICENSE$
0090 +**
0091 +****************************************************************************/
0092 +
0093 +#include "KisGLImageF16.h"
0094 +
0095 +#include <QByteArray>
0096 +#include <QSize>
0097 +
0098 +struct KisGLImageF16::Private : public QSharedData
0099 +{
0100 +    QSize size;
0101 +    QByteArray data;
0102 +};
0103 +
0104 +KisGLImageF16::KisGLImageF16()
0105 +    : m_d(new Private)
0106 +{
0107 +}
0108 +
0109 +KisGLImageF16::KisGLImageF16(const QSize &size, bool clearPixels)
0110 +    : m_d(new Private)
0111 +{
0112 +    resize(size, clearPixels);
0113 +}
0114 +
0115 +KisGLImageF16::KisGLImageF16(int width, int height, bool clearPixels)
0116 +    : KisGLImageF16(QSize(width, height), clearPixels)
0117 +{
0118 +}
0119 +
0120 +KisGLImageF16::KisGLImageF16(const KisGLImageF16 &rhs)
0121 +    : m_d(rhs.m_d)
0122 +{
0123 +}
0124 +
0125 +KisGLImageF16 &KisGLImageF16::operator=(const KisGLImageF16 &rhs)
0126 +{
0127 +    m_d = rhs.m_d;
0128 +}
0129 +
0130 +bool operator==(const KisGLImageF16 &lhs, const KisGLImageF16 &rhs)
0131 +{
0132 +    return lhs.m_d == rhs.m_d;
0133 +}
0134 +
0135 +bool operator!=(const KisGLImageF16 &lhs, const KisGLImageF16 &rhs)
0136 +{
0137 +    return !(lhs == rhs);
0138 +}
0139 +
0140 +KisGLImageF16::~KisGLImageF16()
0141 +{
0142 +}
0143 +
0144 +void KisGLImageF16::clearPixels()
0145 +{
0146 +    if (!m_d->data.isEmpty()) {
0147 +        m_d->data.fill(0);
0148 +    }
0149 +}
0150 +
0151 +void KisGLImageF16::resize(const QSize &size, bool clearPixels)
0152 +{
0153 +    const int pixelSize = 2 * 4;
0154 +
0155 +    m_d->size = size;
0156 +    m_d->data.resize(size.width() * size.height() * pixelSize);
0157 +
0158 +    if (clearPixels) {
0159 +        m_d->data.fill(0);
0160 +    }
0161 +}
0162 +
0163 +const qfloat16 *KisGLImageF16::constData() const
0164 +{
0165 +    Q_ASSERT(!m_d->data.isNull());
0166 +    return reinterpret_cast<const qfloat16*>(m_d->data.data());
0167 +}
0168 +
0169 +qfloat16 *KisGLImageF16::data()
0170 +{
0171 +    m_d->data.detach();
0172 +    Q_ASSERT(!m_d->data.isNull());
0173 +
0174 +    return reinterpret_cast<qfloat16*>(m_d->data.data());
0175 +}
0176 +
0177 +QSize KisGLImageF16::size() const
0178 +{
0179 +    return m_d->size;
0180 +}
0181 +
0182 +int KisGLImageF16::width() const
0183 +{
0184 +    return m_d->size.width();
0185 +}
0186 +
0187 +int KisGLImageF16::height() const
0188 +{
0189 +    return m_d->size.height();
0190 +}
0191 +
0192 +bool KisGLImageF16::isNull() const
0193 +{
0194 +    return m_d->data.isNull();
0195 +}
0196 diff --git a/tests/manual/hdr-qopenglwidget/KisGLImageF16.h b/tests/manual/hdr-qopenglwidget/KisGLImageF16.h
0197 new file mode 100644
0198 index 0000000000..335e42ee68
0199 --- /dev/null
0200 +++ b/tests/manual/hdr-qopenglwidget/KisGLImageF16.h
0201 @@ -0,0 +1,68 @@
0202 +/****************************************************************************
0203 +**
0204 +** Copyright (C) 2019 The Qt Company Ltd.
0205 +** Contact: https://www.qt.io/licensing/
0206 +**
0207 +** This file is part of the test suite of the Qt Toolkit.
0208 +**
0209 +** $QT_BEGIN_LICENSE:GPL-EXCEPT$
0210 +** Commercial License Usage
0211 +** Licensees holding valid commercial Qt licenses may use this file in
0212 +** accordance with the commercial license agreement provided with the
0213 +** Software or, alternatively, in accordance with the terms contained in
0214 +** a written agreement between you and The Qt Company. For licensing terms
0215 +** and conditions see https://www.qt.io/terms-conditions. For further
0216 +** information use the contact form at https://www.qt.io/contact-us.
0217 +**
0218 +** GNU General Public License Usage
0219 +** Alternatively, this file may be used under the terms of the GNU
0220 +** General Public License version 3 as published by the Free Software
0221 +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
0222 +** included in the packaging of this file. Please review the following
0223 +** information to ensure the GNU General Public License requirements will
0224 +** be met: https://www.gnu.org/licenses/gpl-3.0.html.
0225 +**
0226 +** $QT_END_LICENSE$
0227 +**
0228 +****************************************************************************/
0229 +
0230 +#ifndef KISGLIMAGEF16_H
0231 +#define KISGLIMAGEF16_H
0232 +
0233 +#include <QSharedDataPointer>
0234 +#include <QFloat16>
0235 +
0236 +class QSize;
0237 +
0238 +class KisGLImageF16
0239 +{
0240 +public:
0241 +    KisGLImageF16();
0242 +    KisGLImageF16(const QSize &size, bool clearPixels = false);
0243 +    KisGLImageF16(int width, int height, bool clearPixels = false);
0244 +    KisGLImageF16(const KisGLImageF16 &rhs);
0245 +    KisGLImageF16& operator=(const KisGLImageF16 &rhs);
0246 +
0247 +    friend bool operator==(const KisGLImageF16 &lhs, const KisGLImageF16 &rhs);
0248 +    friend bool operator!=(const KisGLImageF16 &lhs, const KisGLImageF16 &rhs);
0249 +
0250 +    ~KisGLImageF16();
0251 +
0252 +    void clearPixels();
0253 +    void resize(const QSize &size, bool clearPixels = false);
0254 +
0255 +    const qfloat16* constData() const;
0256 +    qfloat16* data();
0257 +
0258 +    QSize size() const;
0259 +    int width() const;
0260 +    int height() const;
0261 +
0262 +    bool isNull() const;
0263 +
0264 +private:
0265 +    struct Private;
0266 +    QSharedDataPointer<Private> m_d;
0267 +};
0268 +
0269 +#endif // KISGLIMAGEF16_H
0270 diff --git a/tests/manual/hdr-qopenglwidget/KisGLImageWidget.cpp b/tests/manual/hdr-qopenglwidget/KisGLImageWidget.cpp
0271 new file mode 100644
0272 index 0000000000..da36ac1619
0273 --- /dev/null
0274 +++ b/tests/manual/hdr-qopenglwidget/KisGLImageWidget.cpp
0275 @@ -0,0 +1,252 @@
0276 +/****************************************************************************
0277 +**
0278 +** Copyright (C) 2019 The Qt Company Ltd.
0279 +** Contact: https://www.qt.io/licensing/
0280 +**
0281 +** This file is part of the test suite of the Qt Toolkit.
0282 +**
0283 +** $QT_BEGIN_LICENSE:GPL-EXCEPT$
0284 +** Commercial License Usage
0285 +** Licensees holding valid commercial Qt licenses may use this file in
0286 +** accordance with the commercial license agreement provided with the
0287 +** Software or, alternatively, in accordance with the terms contained in
0288 +** a written agreement between you and The Qt Company. For licensing terms
0289 +** and conditions see https://www.qt.io/terms-conditions. For further
0290 +** information use the contact form at https://www.qt.io/contact-us.
0291 +**
0292 +** GNU General Public License Usage
0293 +** Alternatively, this file may be used under the terms of the GNU
0294 +** General Public License version 3 as published by the Free Software
0295 +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
0296 +** included in the packaging of this file. Please review the following
0297 +** information to ensure the GNU General Public License requirements will
0298 +** be met: https://www.gnu.org/licenses/gpl-3.0.html.
0299 +**
0300 +** $QT_END_LICENSE$
0301 +**
0302 +****************************************************************************/
0303 +
0304 +#include "KisGLImageWidget.h"
0305 +
0306 +#include <QPainter>
0307 +#include <QFile>
0308 +#include <QResizeEvent>
0309 +
0310 +#include "KisGLImageF16.h"
0311 +
0312 +namespace {
0313 +inline void rectToVertices(QVector3D* vertices, const QRectF &rc)
0314 +{
0315 +    vertices[0] = QVector3D(rc.left(),  rc.bottom(), 0.f);
0316 +    vertices[1] = QVector3D(rc.left(),  rc.top(),    0.f);
0317 +    vertices[2] = QVector3D(rc.right(), rc.bottom(), 0.f);
0318 +    vertices[3] = QVector3D(rc.left(),  rc.top(), 0.f);
0319 +    vertices[4] = QVector3D(rc.right(), rc.top(), 0.f);
0320 +    vertices[5] = QVector3D(rc.right(), rc.bottom(),    0.f);
0321 +}
0322 +
0323 +inline void rectToTexCoords(QVector2D* texCoords, const QRectF &rc)
0324 +{
0325 +    texCoords[0] = QVector2D(rc.left(), rc.bottom());
0326 +    texCoords[1] = QVector2D(rc.left(), rc.top());
0327 +    texCoords[2] = QVector2D(rc.right(), rc.bottom());
0328 +    texCoords[3] = QVector2D(rc.left(), rc.top());
0329 +    texCoords[4] = QVector2D(rc.right(), rc.top());
0330 +    texCoords[5] = QVector2D(rc.right(), rc.bottom());
0331 +}
0332 +}
0333 +
0334 +KisGLImageWidget::KisGLImageWidget(QWidget *parent)
0335 +    : KisGLImageWidget(QSurfaceFormat::sRGBColorSpace, parent)
0336 +{
0337 +}
0338 +
0339 +KisGLImageWidget::KisGLImageWidget(QSurfaceFormat::ColorSpace colorSpace,
0340 +                                   QWidget *parent)
0341 +    : QOpenGLWidget(parent),
0342 +      m_texture(QOpenGLTexture::Target2D)
0343 +{
0344 +
0345 +    qDebug() << "Crating gl widget";
0346 +
0347 +    setTextureFormat(GL_RGBA16F);
0348 +    setTextureColorSpace(colorSpace);
0349 +
0350 +    setUpdateBehavior(QOpenGLWidget::NoPartialUpdate);
0351 +}
0352 +
0353 +void KisGLImageWidget::initializeGL()
0354 +{
0355 +    initializeOpenGLFunctions();
0356 +
0357 +    qDebug() << "Initialized with format:" << context()->format();
0358 +
0359 +    QFile vertexShaderFile(QString(":/") + "kis_gl_image_widget.vert");
0360 +    vertexShaderFile.open(QIODevice::ReadOnly);
0361 +    QString vertSource = vertexShaderFile.readAll();
0362 +
0363 +    QFile fragShaderFile(QString(":/") + "kis_gl_image_widget.frag");
0364 +    fragShaderFile.open(QIODevice::ReadOnly);
0365 +    QString fragSource = fragShaderFile.readAll();
0366 +
0367 +    if (context()->isOpenGLES()) {
0368 +        const char *versionHelper = "#define USE_OPENGLES\n";
0369 +        vertSource.prepend(versionHelper);
0370 +        fragSource.prepend(versionHelper);
0371 +
0372 +        const char *versionDefinition = "#version 100\n";
0373 +        vertSource.prepend(versionDefinition);
0374 +        fragSource.prepend(versionDefinition);
0375 +    } else {
0376 +        const char *versionDefinition = "#version 330 core\n";
0377 +        vertSource.prepend(versionDefinition);
0378 +        fragSource.prepend(versionDefinition);
0379 +    }
0380 +
0381 +    if (!m_shader.addShaderFromSourceCode(QOpenGLShader::Vertex, vertSource)) {
0382 +        qDebug() << "Could not add vertex code";
0383 +        return;
0384 +    }
0385 +
0386 +    if (!m_shader.addShaderFromSourceCode(QOpenGLShader::Fragment, fragSource)) {
0387 +        qDebug() << "Could not add fragment code";
0388 +        return;
0389 +    }
0390 +
0391 +    if (!m_shader.link()) {
0392 +        qDebug() << "Could not link";
0393 +        return;
0394 +    }
0395 +
0396 +    if (!m_shader.bind()) {
0397 +        qDebug() << "Could not bind";
0398 +        return;
0399 +    }
0400 +
0401 +    m_shader.release();
0402 +
0403 +
0404 +    m_vao.create();
0405 +    m_vao.bind();
0406 +
0407 +    m_verticesBuffer.create();
0408 +    updateVerticesBuffer(this->rect());
0409 +
0410 +    QVector<QVector2D> textureVertices(6);
0411 +    rectToTexCoords(textureVertices.data(), QRect(0.0, 0.0, 1.0, 1.0));
0412 +
0413 +    m_textureVerticesBuffer.create();
0414 +    m_textureVerticesBuffer.bind();
0415 +    m_textureVerticesBuffer.setUsagePattern(QOpenGLBuffer::DynamicDraw);
0416 +    m_textureVerticesBuffer.allocate(2 * 3 * sizeof(QVector2D));
0417 +    m_verticesBuffer.write(0, textureVertices.data(), m_textureVerticesBuffer.size());
0418 +    m_textureVerticesBuffer.release();
0419 +
0420 +    m_vao.release();
0421 +
0422 +
0423 +    if (!m_sourceImage.isNull()) {
0424 +        loadImage(m_sourceImage);
0425 +    }
0426 +}
0427 +
0428 +void KisGLImageWidget::updateVerticesBuffer(const QRect &rect)
0429 +{
0430 +    if (!m_vao.isCreated() || !m_verticesBuffer.isCreated()) return;
0431 +
0432 +    QVector<QVector3D> vertices(6);
0433 +    rectToVertices(vertices.data(), rect);
0434 +
0435 +    m_verticesBuffer.bind();
0436 +    m_verticesBuffer.setUsagePattern(QOpenGLBuffer::DynamicDraw);
0437 +    m_verticesBuffer.allocate(2 * 3 * sizeof(QVector3D));
0438 +    m_verticesBuffer.write(0, vertices.data(), m_verticesBuffer.size());
0439 +    m_verticesBuffer.release();
0440 +}
0441 +
0442 +
0443 +void KisGLImageWidget::paintGL()
0444 +{
0445 +    const QColor bgColor = palette().background().color();
0446 +    glClearColor(bgColor.redF(), bgColor.greenF(), bgColor.blueF(), 1.0f);
0447 +    glClear(GL_COLOR_BUFFER_BIT);
0448 +
0449 +    if (!m_texture.isCreated()) return;
0450 +
0451 +    glViewport(0, 0, width(), height());
0452 +
0453 +    m_vao.bind();
0454 +    m_shader.bind();
0455 +
0456 +    {
0457 +        QMatrix4x4 projectionMatrix;
0458 +        projectionMatrix.setToIdentity();
0459 +        projectionMatrix.ortho(0, width(), height(), 0, -1, 1);
0460 +        QMatrix4x4 viewProjectionMatrix;
0461 +
0462 +        // use a QTransform to scale, translate, rotate your view
0463 +        QTransform transform; // TODO: noop!
0464 +        viewProjectionMatrix = projectionMatrix * QMatrix4x4(transform);
0465 +
0466 +        m_shader.setUniformValue("viewProjectionMatrix", viewProjectionMatrix);
0467 +    }
0468 +
0469 +    m_shader.enableAttributeArray("vertexPosition");
0470 +    m_verticesBuffer.bind();
0471 +    m_shader.setAttributeBuffer("vertexPosition", GL_FLOAT, 0, 3);
0472 +
0473 +    m_shader.enableAttributeArray("texturePosition");
0474 +    m_textureVerticesBuffer.bind();
0475 +    m_shader.setAttributeBuffer("texturePosition", GL_FLOAT, 0, 2);
0476 +
0477 +    glActiveTexture(GL_TEXTURE0);
0478 +    m_texture.bind();
0479 +
0480 +    // draw 2 triangles = 6 vertices starting at offset 0 in the buffer
0481 +    glDrawArrays(GL_TRIANGLES, 0, 6);
0482 +
0483 +    m_verticesBuffer.release();
0484 +    m_textureVerticesBuffer.release();
0485 +    m_texture.release();
0486 +    m_shader.release();
0487 +    m_vao.release();
0488 +}
0489 +
0490 +void KisGLImageWidget::loadImage(const KisGLImageF16 &image)
0491 +{
0492 +    if (m_sourceImage != image) {
0493 +        m_sourceImage = image;
0494 +    }
0495 +
0496 +    if (m_vao.isCreated()) {
0497 +        m_texture.setFormat(QOpenGLTexture::RGBA16F);
0498 +        m_texture.setSize(image.width(), image.height());
0499 +        m_texture.allocateStorage(QOpenGLTexture::RGBA, QOpenGLTexture::Float16);
0500 +        m_texture.setMinificationFilter(QOpenGLTexture::LinearMipMapLinear);
0501 +        m_texture.setMagnificationFilter(QOpenGLTexture::Linear);
0502 +        m_texture.setData(QOpenGLTexture::RGBA, QOpenGLTexture::Float16, image.constData());
0503 +        updateGeometry();
0504 +    }
0505 +}
0506 +
0507 +void KisGLImageWidget::paintEvent(QPaintEvent *event)
0508 +{
0509 +    QOpenGLWidget::paintEvent(event);
0510 +}
0511 +
0512 +void KisGLImageWidget::resizeEvent(QResizeEvent *event)
0513 +{
0514 +    updateVerticesBuffer(QRect(QPoint(),event->size()));
0515 +    QOpenGLWidget::resizeEvent(event);
0516 +}
0517 +
0518 +QSize KisGLImageWidget::sizeHint() const
0519 +{
0520 +    return m_sourceImage.size();
0521 +}
0522 +
0523 +KisGLImageF16 KisGLImageWidget::image() const
0524 +{
0525 +    return m_sourceImage;
0526 +}
0527 +
0528 diff --git a/tests/manual/hdr-qopenglwidget/KisGLImageWidget.h b/tests/manual/hdr-qopenglwidget/KisGLImageWidget.h
0529 new file mode 100644
0530 index 0000000000..e807064cb4
0531 --- /dev/null
0532 +++ b/tests/manual/hdr-qopenglwidget/KisGLImageWidget.h
0533 @@ -0,0 +1,77 @@
0534 +/****************************************************************************
0535 +**
0536 +** Copyright (C) 2019 The Qt Company Ltd.
0537 +** Contact: https://www.qt.io/licensing/
0538 +**
0539 +** This file is part of the test suite of the Qt Toolkit.
0540 +**
0541 +** $QT_BEGIN_LICENSE:GPL-EXCEPT$
0542 +** Commercial License Usage
0543 +** Licensees holding valid commercial Qt licenses may use this file in
0544 +** accordance with the commercial license agreement provided with the
0545 +** Software or, alternatively, in accordance with the terms contained in
0546 +** a written agreement between you and The Qt Company. For licensing terms
0547 +** and conditions see https://www.qt.io/terms-conditions. For further
0548 +** information use the contact form at https://www.qt.io/contact-us.
0549 +**
0550 +** GNU General Public License Usage
0551 +** Alternatively, this file may be used under the terms of the GNU
0552 +** General Public License version 3 as published by the Free Software
0553 +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
0554 +** included in the packaging of this file. Please review the following
0555 +** information to ensure the GNU General Public License requirements will
0556 +** be met: https://www.gnu.org/licenses/gpl-3.0.html.
0557 +**
0558 +** $QT_END_LICENSE$
0559 +**
0560 +****************************************************************************/
0561 +
0562 +#ifndef KISGLIMAGEWIDGET_H
0563 +#define KISGLIMAGEWIDGET_H
0564 +
0565 +#include <QOpenGLWidget>
0566 +#include <QOpenGLFunctions>
0567 +#include <QOpenGLTexture>
0568 +#include <QOpenGLShaderProgram>
0569 +#include <QOpenGLVertexArrayObject>
0570 +#include <QOpenGLBuffer>
0571 +#include <QTransform>
0572 +#include <KisGLImageF16.h>
0573 +
0574 +
0575 +class KisGLImageWidget : public QOpenGLWidget, protected QOpenGLFunctions
0576 +{
0577 +    Q_OBJECT
0578 +public:
0579 +    KisGLImageWidget(QWidget *parent = nullptr);
0580 +    KisGLImageWidget(QSurfaceFormat::ColorSpace colorSpace,
0581 +                     QWidget *parent = nullptr);
0582 +
0583 +    void initializeGL() override;
0584 +    void paintGL() override;
0585 +
0586 +    void loadImage(const KisGLImageF16 &image);
0587 +
0588 +    void paintEvent(QPaintEvent *event) override;
0589 +    void resizeEvent(QResizeEvent *event) override;
0590 +
0591 +    QSize sizeHint() const override;
0592 +
0593 +    KisGLImageF16 image() const;
0594 +
0595 +public Q_SLOTS:
0596 +
0597 +private:
0598 +    void updateVerticesBuffer(const QRect &rect);
0599 +
0600 +private:
0601 +    KisGLImageF16 m_sourceImage;
0602 +
0603 +    QOpenGLShaderProgram m_shader;
0604 +    QOpenGLVertexArrayObject m_vao;
0605 +    QOpenGLBuffer m_verticesBuffer;
0606 +    QOpenGLBuffer m_textureVerticesBuffer;
0607 +    QOpenGLTexture m_texture;
0608 +};
0609 +
0610 +#endif // KISGLIMAGEWIDGET_H
0611 diff --git a/tests/manual/hdr-qopenglwidget/hdr-openglwidget.pro b/tests/manual/hdr-qopenglwidget/hdr-openglwidget.pro
0612 new file mode 100644
0613 index 0000000000..b418e54b43
0614 --- /dev/null
0615 +++ b/tests/manual/hdr-qopenglwidget/hdr-openglwidget.pro
0616 @@ -0,0 +1,20 @@
0617 +QT += widgets widgets-private gui-private core-private
0618 +
0619 +TARGET = hdr-openglwidget
0620 +TEMPLATE = app
0621 +
0622 +SOURCES += main.cpp \
0623 +        #hdr-openglwidget.cpp \
0624 +        openglprobeutils.cpp \
0625 +        KisGLImageWidget.cpp \
0626 +        KisGLImageF16.cpp \
0627 +        window.cpp
0628 +
0629 +HEADERS  += \
0630 +#hdr-openglwidget.h \
0631 +    openglprobeutils.h \
0632 +    KisGLImageWidget.h \
0633 +    KisGLImageF16.h \
0634 +    window.h
0635 +
0636 +RESOURCES += kis_gl_image_widget.qrc
0637 diff --git a/tests/manual/hdr-qopenglwidget/kis_gl_image_widget.frag b/tests/manual/hdr-qopenglwidget/kis_gl_image_widget.frag
0638 new file mode 100644
0639 index 0000000000..b57c657046
0640 --- /dev/null
0641 +++ b/tests/manual/hdr-qopenglwidget/kis_gl_image_widget.frag
0642 @@ -0,0 +1,23 @@
0643 +#ifndef USE_OPENGLES
0644 +#define INATTR in
0645 +#define OUTATTR out
0646 +#define DECLARE_OUT_VAR out vec4 f_fragColor;
0647 +#define OUT_VAR f_fragColor
0648 +#define highp
0649 +#define texture2D texture
0650 +#else
0651 +#define INATTR varying
0652 +#define DECLARE_OUT_VAR
0653 +#define OUT_VAR gl_FragColor
0654 +#endif
0655 +// vertices data
0656 +INATTR highp vec4 textureCoordinates;
0657 +uniform sampler2D f_tileTexture;
0658 +DECLARE_OUT_VAR
0659 +
0660 +void main()
0661 +{
0662 +    // get the fragment color from the tile texture
0663 +    highp vec4 color = texture2D(f_tileTexture, textureCoordinates.st);
0664 +    OUT_VAR = vec4(color);
0665 +}
0666 diff --git a/tests/manual/hdr-qopenglwidget/kis_gl_image_widget.qrc b/tests/manual/hdr-qopenglwidget/kis_gl_image_widget.qrc
0667 new file mode 100644
0668 index 0000000000..ab5b5719a9
0669 --- /dev/null
0670 +++ b/tests/manual/hdr-qopenglwidget/kis_gl_image_widget.qrc
0671 @@ -0,0 +1,6 @@
0672 +<RCC>
0673 +    <qresource prefix="/">
0674 +        <file>kis_gl_image_widget.frag</file>
0675 +        <file>kis_gl_image_widget.vert</file>
0676 +    </qresource>
0677 +</RCC>
0678 diff --git a/tests/manual/hdr-qopenglwidget/kis_gl_image_widget.vert b/tests/manual/hdr-qopenglwidget/kis_gl_image_widget.vert
0679 new file mode 100644
0680 index 0000000000..9578f47945
0681 --- /dev/null
0682 +++ b/tests/manual/hdr-qopenglwidget/kis_gl_image_widget.vert
0683 @@ -0,0 +1,17 @@
0684 +#ifndef USE_OPENGLES
0685 +#define INATTR in
0686 +#define OUTATTR out
0687 +#define highp
0688 +#else
0689 +#define INATTR attribute
0690 +#define OUTATTR varying
0691 +#endif
0692 +uniform mat4 viewProjectionMatrix;
0693 +INATTR highp vec3 vertexPosition;
0694 +INATTR highp vec2 texturePosition;
0695 +OUTATTR highp vec4 textureCoordinates;
0696 +void main()
0697 +{
0698 +   textureCoordinates = vec4(texturePosition.x, texturePosition.y, 0.0, 1.0);
0699 +   gl_Position = viewProjectionMatrix * vec4(vertexPosition.x, vertexPosition.y, 0.0, 1.0);
0700 +}
0701 diff --git a/tests/manual/hdr-qopenglwidget/main.cpp b/tests/manual/hdr-qopenglwidget/main.cpp
0702 new file mode 100644
0703 index 0000000000..e517ef8579
0704 --- /dev/null
0705 +++ b/tests/manual/hdr-qopenglwidget/main.cpp
0706 @@ -0,0 +1,153 @@
0707 +/****************************************************************************
0708 +**
0709 +** Copyright (C) 2016 The Qt Company Ltd.
0710 +** Contact: https://www.qt.io/licensing/
0711 +**
0712 +** This file is part of the test suite of the Qt Toolkit.
0713 +**
0714 +** $QT_BEGIN_LICENSE:GPL-EXCEPT$
0715 +** Commercial License Usage
0716 +** Licensees holding valid commercial Qt licenses may use this file in
0717 +** accordance with the commercial license agreement provided with the
0718 +** Software or, alternatively, in accordance with the terms contained in
0719 +** a written agreement between you and The Qt Company. For licensing terms
0720 +** and conditions see https://www.qt.io/terms-conditions. For further
0721 +** information use the contact form at https://www.qt.io/contact-us.
0722 +**
0723 +** GNU General Public License Usage
0724 +** Alternatively, this file may be used under the terms of the GNU
0725 +** General Public License version 3 as published by the Free Software
0726 +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
0727 +** included in the packaging of this file. Please review the following
0728 +** information to ensure the GNU General Public License requirements will
0729 +** be met: https://www.gnu.org/licenses/gpl-3.0.html.
0730 +**
0731 +** $QT_END_LICENSE$
0732 +**
0733 +****************************************************************************/
0734 +
0735 +#include <QApplication>
0736 +#include "window.h"
0737 +
0738 +#include "openglprobeutils.h"
0739 +#include <QDebug>
0740 +
0741 +QSurfaceFormat generateSurfaceFormat(QSurfaceFormat::RenderableType renderer,
0742 +                                     QSurfaceFormat::ColorSpace colorSpace,
0743 +                                     int bitDepth)
0744 +{
0745 +    QSurfaceFormat format;
0746 +#ifdef Q_OS_MACOS
0747 +    format.setVersion(3, 2);
0748 +    format.setProfile(QSurfaceFormat::CoreProfile);
0749 +#else
0750 +    format.setVersion(3, 0);
0751 +    format.setProfile(QSurfaceFormat::CoreProfile);
0752 +#endif
0753 +    format.setDepthBufferSize(24);
0754 +    format.setStencilBufferSize(8);
0755 +
0756 +    switch (bitDepth) {
0757 +    case 8:
0758 +        format.setRedBufferSize(8);
0759 +        format.setGreenBufferSize(8);
0760 +        format.setBlueBufferSize(8);
0761 +        format.setAlphaBufferSize(8);
0762 +        break;
0763 +    case 10:
0764 +        format.setRedBufferSize(10);
0765 +        format.setGreenBufferSize(10);
0766 +        format.setBlueBufferSize(10);
0767 +        format.setAlphaBufferSize(2);
0768 +        break;
0769 +    case 16:
0770 +        format.setRedBufferSize(16);
0771 +        format.setGreenBufferSize(16);
0772 +        format.setBlueBufferSize(16);
0773 +        format.setAlphaBufferSize(16);
0774 +        break;
0775 +    default:
0776 +        qFatal("Unsupported surface bit depth %d", bitDepth);
0777 +    }
0778 +
0779 +    format.setRenderableType(renderer);
0780 +    format.setColorSpace(colorSpace);
0781 +
0782 +    format.setSwapBehavior(QSurfaceFormat::DoubleBuffer);
0783 +    format.setSwapInterval(0); // Disable vertical refresh syncing
0784 +
0785 +    return format;
0786 +}
0787 +
0788 +int main(int argc, char *argv[])
0789 +{
0790 +    QVector<QSurfaceFormat> allFormats;
0791 +
0792 +    QVector<QSurfaceFormat::RenderableType> availableRenderers;
0793 +    availableRenderers << QSurfaceFormat::OpenGL;
0794 +    availableRenderers << QSurfaceFormat::OpenGLES;
0795 +
0796 +    for (QSurfaceFormat::RenderableType renderer : availableRenderers) {
0797 +        allFormats << generateSurfaceFormat(renderer, QSurfaceFormat::sRGBColorSpace, 8);
0798 +        allFormats << generateSurfaceFormat(renderer, QSurfaceFormat::bt2020PQColorSpace, 8);
0799 +        allFormats << generateSurfaceFormat(renderer, QSurfaceFormat::sRGBColorSpace, 10);
0800 +        allFormats << generateSurfaceFormat(renderer, QSurfaceFormat::bt2020PQColorSpace, 10);
0801 +        allFormats << generateSurfaceFormat(renderer, QSurfaceFormat::scRGBColorSpace, 16);
0802 +    }
0803 +
0804 +    for (QSurfaceFormat format : allFormats) {
0805 +        qDebug() << "Probing: " << format;
0806 +        bool result = OpenGLProbeUtils::probeFormat(format, true);
0807 +        qDebug() << "    result:" << result;
0808 +    }
0809 +
0810 +
0811 +    if (argc > 1 && !strcmp(argv[1], "--sharecontext")) {
0812 +        qDebug("Requesting all contexts to share");
0813 +        QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts);
0814 +    }
0815 +
0816 +    QApplication a(argc, argv);
0817 +
0818 +    QSurfaceFormat::RenderableType renderer = QSurfaceFormat::OpenGLES;
0819 +    QSurfaceFormat::ColorSpace colorSpace = QSurfaceFormat::scRGBColorSpace;
0820 +    int bitDepth = 16;
0821 +
0822 +
0823 +    if (QCoreApplication::arguments().contains(QLatin1String("--scrgb"))) {
0824 +        colorSpace = QSurfaceFormat::scRGBColorSpace;
0825 +        bitDepth = 16;
0826 +    } else if (QCoreApplication::arguments().contains(QLatin1String("--bt2020pq"))) {
0827 +        colorSpace = QSurfaceFormat::bt2020PQColorSpace;
0828 +        bitDepth = 10;
0829 +    } else if (QCoreApplication::arguments().contains(QLatin1String("--srgb"))) {
0830 +        colorSpace = QSurfaceFormat::sRGBColorSpace;
0831 +        bitDepth = 8;
0832 +    }
0833 +
0834 +    if (QCoreApplication::arguments().contains(QLatin1String("--opengl"))) {
0835 +        renderer = QSurfaceFormat::OpenGL;
0836 +    } else if (QCoreApplication::arguments().contains(QLatin1String("--opengles"))) {
0837 +        renderer = QSurfaceFormat::OpenGLES;
0838 +    }
0839 +
0840 +    QSurfaceFormat format = generateSurfaceFormat(renderer, colorSpace, bitDepth);
0841 +
0842 +    if (QCoreApplication::arguments().contains(QLatin1String("--multisample"))) {
0843 +        format.setSamples(4);
0844 +    }
0845 +
0846 +    if (format.renderableType() == QSurfaceFormat::OpenGL) {
0847 +        QCoreApplication::setAttribute(Qt::AA_UseDesktopOpenGL, true);
0848 +    } else if (format.renderableType() == QSurfaceFormat::OpenGLES) {
0849 +        QCoreApplication::setAttribute(Qt::AA_UseOpenGLES, true);
0850 +    }
0851 +
0852 +    qDebug() << "Requesting" << format.renderableType() << format;
0853 +    QSurfaceFormat::setDefaultFormat(format);
0854 +
0855 +    Window window;
0856 +    window.show();
0857 +
0858 +    return a.exec();
0859 +}
0860 diff --git a/tests/manual/hdr-qopenglwidget/openglprobeutils.cpp b/tests/manual/hdr-qopenglwidget/openglprobeutils.cpp
0861 new file mode 100644
0862 index 0000000000..687cc08904
0863 --- /dev/null
0864 +++ b/tests/manual/hdr-qopenglwidget/openglprobeutils.cpp
0865 @@ -0,0 +1,139 @@
0866 +/****************************************************************************
0867 +**
0868 +** Copyright (C) 2019 The Qt Company Ltd.
0869 +** Contact: https://www.qt.io/licensing/
0870 +**
0871 +** This file is part of the test suite of the Qt Toolkit.
0872 +**
0873 +** $QT_BEGIN_LICENSE:GPL-EXCEPT$
0874 +** Commercial License Usage
0875 +** Licensees holding valid commercial Qt licenses may use this file in
0876 +** accordance with the commercial license agreement provided with the
0877 +** Software or, alternatively, in accordance with the terms contained in
0878 +** a written agreement between you and The Qt Company. For licensing terms
0879 +** and conditions see https://www.qt.io/terms-conditions. For further
0880 +** information use the contact form at https://www.qt.io/contact-us.
0881 +**
0882 +** GNU General Public License Usage
0883 +** Alternatively, this file may be used under the terms of the GNU
0884 +** General Public License version 3 as published by the Free Software
0885 +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
0886 +** included in the packaging of this file. Please review the following
0887 +** information to ensure the GNU General Public License requirements will
0888 +** be met: https://www.gnu.org/licenses/gpl-3.0.html.
0889 +**
0890 +** $QT_END_LICENSE$
0891 +**
0892 +****************************************************************************/
0893 +
0894 +#include "openglprobeutils.h"
0895 +
0896 +#include <QApplication>
0897 +#include <QSurfaceFormat>
0898 +#include <QOpenGLContext>
0899 +#include <QDebug>
0900 +#include <QWindow>
0901 +
0902 +namespace OpenGLProbeUtils {
0903 +
0904 +namespace {
0905 +
0906 +struct AppAttributeSetter
0907 +{
0908 +    AppAttributeSetter(Qt::ApplicationAttribute attribute, bool useOpenGLES)
0909 +        : m_attribute(attribute),
0910 +          m_oldValue(QCoreApplication::testAttribute(attribute))
0911 +    {
0912 +        QCoreApplication::setAttribute(attribute, useOpenGLES);
0913 +    }
0914 +
0915 +    ~AppAttributeSetter() {
0916 +        QCoreApplication::setAttribute(m_attribute, m_oldValue);
0917 +    }
0918 +
0919 +private:
0920 +    Qt::ApplicationAttribute m_attribute;
0921 +    bool m_oldValue = false;
0922 +};
0923 +
0924 +struct SurfaceFormatSetter
0925 +{
0926 +    SurfaceFormatSetter(const QSurfaceFormat &format)
0927 +        : m_oldFormat(QSurfaceFormat::defaultFormat())
0928 +    {
0929 +        QSurfaceFormat::setDefaultFormat(format);
0930 +    }
0931 +
0932 +    ~SurfaceFormatSetter() {
0933 +        QSurfaceFormat::setDefaultFormat(m_oldFormat);
0934 +    }
0935 +
0936 +private:
0937 +    QSurfaceFormat m_oldFormat;
0938 +};
0939 +
0940 +}
0941 +
0942 +bool fuzzyCompareColorSpaces(const QSurfaceFormat::ColorSpace &lhs, const QSurfaceFormat::ColorSpace &rhs)
0943 +{
0944 +    return lhs == rhs ||
0945 +        ((lhs == QSurfaceFormat::DefaultColorSpace ||
0946 +          lhs == QSurfaceFormat::sRGBColorSpace) &&
0947 +         (rhs == QSurfaceFormat::DefaultColorSpace ||
0948 +          rhs == QSurfaceFormat::sRGBColorSpace));
0949 +}
0950 +
0951 +bool probeFormat(const QSurfaceFormat &format, bool adjustGlobalState)
0952 +{
0953 +    QScopedPointer<AppAttributeSetter> sharedContextSetter;
0954 +    QScopedPointer<AppAttributeSetter> glSetter;
0955 +    QScopedPointer<AppAttributeSetter> glesSetter;
0956 +    QScopedPointer<SurfaceFormatSetter> formatSetter;
0957 +    QScopedPointer<QApplication> application;
0958 +
0959 +    if (adjustGlobalState) {
0960 +        sharedContextSetter.reset(new AppAttributeSetter(Qt::AA_ShareOpenGLContexts, false));
0961 +
0962 +        if (format.renderableType() != QSurfaceFormat::DefaultRenderableType) {
0963 +            glSetter.reset(new AppAttributeSetter(Qt::AA_UseDesktopOpenGL, format.renderableType() != QSurfaceFormat::OpenGLES));
0964 +            glesSetter.reset(new AppAttributeSetter(Qt::AA_UseOpenGLES, format.renderableType() == QSurfaceFormat::OpenGLES));
0965 +        }
0966 +
0967 +        formatSetter.reset(new SurfaceFormatSetter(format));
0968 +
0969 +        int argc = 1;
0970 +        QByteArray data("krita");
0971 +        char *argv = data.data();
0972 +        application.reset(new QApplication(argc, &argv));
0973 +    }
0974 +
0975 +    QWindow surface;
0976 +    surface.setFormat(format);
0977 +    surface.setSurfaceType(QSurface::OpenGLSurface);
0978 +    surface.create();
0979 +    QOpenGLContext context;
0980 +    context.setFormat(format);
0981 +
0982 +
0983 +    if (!context.create()) {
0984 +        qCritical() << "OpenGL context cannot be created";
0985 +        return false;
0986 +    }
0987 +    if (!context.isValid()) {
0988 +        qCritical() << "OpenGL context is not valid while checking Qt's OpenGL status";
0989 +        return false;
0990 +    }
0991 +    if (!context.makeCurrent(&surface)) {
0992 +        qCritical() << "OpenGL context cannot be made current";
0993 +        return false;
0994 +    }
0995 +
0996 +    if (!fuzzyCompareColorSpaces(context.format().colorSpace(), format.colorSpace())) {
0997 +        qCritical() << "Failed to create an OpenGL context with requested color space. Requested:" << format.colorSpace() << "Actual:" << context.format().colorSpace();
0998 +        return false;
0999 +    }
1000 +
1001 +    return true;
1002 +}
1003 +
1004 +}
1005 diff --git a/tests/manual/hdr-qopenglwidget/openglprobeutils.h b/tests/manual/hdr-qopenglwidget/openglprobeutils.h
1006 new file mode 100644
1007 index 0000000000..3b2f1ec3d0
1008 --- /dev/null
1009 +++ b/tests/manual/hdr-qopenglwidget/openglprobeutils.h
1010 @@ -0,0 +1,42 @@
1011 +/****************************************************************************
1012 +**
1013 +** Copyright (C) 2019 The Qt Company Ltd.
1014 +** Contact: https://www.qt.io/licensing/
1015 +**
1016 +** This file is part of the test suite of the Qt Toolkit.
1017 +**
1018 +** $QT_BEGIN_LICENSE:GPL-EXCEPT$
1019 +** Commercial License Usage
1020 +** Licensees holding valid commercial Qt licenses may use this file in
1021 +** accordance with the commercial license agreement provided with the
1022 +** Software or, alternatively, in accordance with the terms contained in
1023 +** a written agreement between you and The Qt Company. For licensing terms
1024 +** and conditions see https://www.qt.io/terms-conditions. For further
1025 +** information use the contact form at https://www.qt.io/contact-us.
1026 +**
1027 +** GNU General Public License Usage
1028 +** Alternatively, this file may be used under the terms of the GNU
1029 +** General Public License version 3 as published by the Free Software
1030 +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
1031 +** included in the packaging of this file. Please review the following
1032 +** information to ensure the GNU General Public License requirements will
1033 +** be met: https://www.gnu.org/licenses/gpl-3.0.html.
1034 +**
1035 +** $QT_END_LICENSE$
1036 +**
1037 +****************************************************************************/
1038 +
1039 +#ifndef OPENGLPROBEUTILS_H
1040 +#define OPENGLPROBEUTILS_H
1041 +
1042 +#include <QSurfaceFormat>
1043 +
1044 +namespace OpenGLProbeUtils
1045 +{
1046 +
1047 +bool fuzzyCompareColorSpaces(const QSurfaceFormat::ColorSpace &lhs, const QSurfaceFormat::ColorSpace &rhs);
1048 +bool probeFormat(const QSurfaceFormat &format, bool adjustGlobalState);
1049 +
1050 +};
1051 +
1052 +#endif // OPENGLPROBEUTILS_H
1053 diff --git a/tests/manual/hdr-qopenglwidget/window.cpp b/tests/manual/hdr-qopenglwidget/window.cpp
1054 new file mode 100644
1055 index 0000000000..5729660a4f
1056 --- /dev/null
1057 +++ b/tests/manual/hdr-qopenglwidget/window.cpp
1058 @@ -0,0 +1,219 @@
1059 +/****************************************************************************
1060 +**
1061 +** Copyright (C) 2019 The Qt Company Ltd.
1062 +** Contact: https://www.qt.io/licensing/
1063 +**
1064 +** This file is part of the test suite of the Qt Toolkit.
1065 +**
1066 +** $QT_BEGIN_LICENSE:GPL-EXCEPT$
1067 +** Commercial License Usage
1068 +** Licensees holding valid commercial Qt licenses may use this file in
1069 +** accordance with the commercial license agreement provided with the
1070 +** Software or, alternatively, in accordance with the terms contained in
1071 +** a written agreement between you and The Qt Company. For licensing terms
1072 +** and conditions see https://www.qt.io/terms-conditions. For further
1073 +** information use the contact form at https://www.qt.io/contact-us.
1074 +**
1075 +** GNU General Public License Usage
1076 +** Alternatively, this file may be used under the terms of the GNU
1077 +** General Public License version 3 as published by the Free Software
1078 +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
1079 +** included in the packaging of this file. Please review the following
1080 +** information to ensure the GNU General Public License requirements will
1081 +** be met: https://www.gnu.org/licenses/gpl-3.0.html.
1082 +**
1083 +** $QT_END_LICENSE$
1084 +**
1085 +****************************************************************************/
1086 +
1087 +#include "window.h"
1088 +
1089 +#include "KisGLImageWidget.h"
1090 +#include "KisGLImageF16.h"
1091 +
1092 +#include <cmath>
1093 +
1094 +#include <QMenu>
1095 +#include <QMenuBar>
1096 +#include <QToolBar>
1097 +#include <QAction>
1098 +#include <QDebug>
1099 +
1100 +#include <QVBoxLayout>
1101 +#include <QHBoxLayout>
1102 +#include <QLabel>
1103 +
1104 +#include <cmath>
1105 +
1106 +
1107 +Window::Window()
1108 +{
1109 +    setWindowTitle("16 bit float QOpenGLWidget test");
1110 +    QMenu *menu = menuBar()->addMenu("File");
1111 +    QToolBar *tb = addToolBar("File");
1112 +
1113 +    m_quitAction = new QAction("Quit", this);
1114 +    connect(m_quitAction, SIGNAL(triggered(bool)), this, SLOT(close()));
1115 +    menu->addAction(m_quitAction);
1116 +    tb->addAction(m_quitAction);
1117 +
1118 +    QWidget *centralWidget = new QWidget(this);
1119 +    QVBoxLayout *layout = new QVBoxLayout(centralWidget);
1120 +
1121 +    QHBoxLayout *hLayout = new QHBoxLayout(centralWidget);
1122 +
1123 +    m_imageWidget = new KisGLImageWidget(QSurfaceFormat::scRGBColorSpace, this);
1124 +    m_imageWidget->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
1125 +    hLayout->addWidget(m_imageWidget, 0, Qt::AlignLeft);
1126 +
1127 +    m_imageWidgetSdr = new KisGLImageWidget(QSurfaceFormat::scRGBColorSpace, this);
1128 +    m_imageWidgetSdr->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
1129 +    hLayout->addWidget(m_imageWidgetSdr, 0, Qt::AlignLeft);
1130 +
1131 +    QImage image(QSize(255,255), QImage::Format_ARGB32);
1132 +    image.fill(Qt::red);
1133 +
1134 +    QLabel *label = new QLabel(this);
1135 +    label->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
1136 +    hLayout->addWidget(label, 0, Qt::AlignLeft);
1137 +
1138 +    m_imageWidget->loadImage(initializeImage(false));
1139 +    m_imageWidgetSdr->loadImage(initializeImage(true));
1140 +    label->setPixmap(QPixmap::fromImage(convertToQImage(m_imageWidget->image())));
1141 +
1142 +    layout->addLayout(hLayout);
1143 +
1144 +    m_lblContextInfo = new QLabel(this);
1145 +    layout->addWidget(m_lblContextInfo);
1146 +
1147 +    QLabel *lblNotes = new QLabel(this);
1148 +    lblNotes->setWordWrap(true);
1149 +    lblNotes->setText("* In SDR display mode all three images should look exactly the same\n"
1150 +                      "* In HDR display mode: image 1 should look brighter than the others "
1151 +                      "(it is HDR), images 2 and 3 should have exactly the same brightness and look");
1152 +
1153 +    layout->addWidget(lblNotes);
1154 +
1155 +    centralWidget->setLayout(layout);
1156 +    setCentralWidget(centralWidget);
1157 +}
1158 +
1159 +inline qfloat16 floatToFloat16(float x) {
1160 +    qfloat16 result;
1161 +    qFloatToFloat16(&result, &x, 1);
1162 +    return result;
1163 +}
1164 +
1165 +inline float float16ToFloat(qfloat16 x) {
1166 +    float result;
1167 +    qFloatFromFloat16(&result, &x, 1);
1168 +    return result;
1169 +}
1170 +
1171 +
1172 +KisGLImageF16 Window::initializeImage(bool cropRange) const
1173 +{
1174 +    const int size = 256;
1175 +    KisGLImageF16 image(size, size);
1176 +    image.clearPixels();
1177 +    qfloat16 *pixelPtr = image.data();
1178 +
1179 +    for (int y = 0; y < size; y++) {
1180 +        for (int x = 0; x < size; x++) {
1181 +            qfloat16 *pxl = reinterpret_cast<qfloat16*>(pixelPtr);
1182 +
1183 +            float hdrRedValue = 25.0f * std::pow(float(x) / size, 5.0f);
1184 +
1185 +            if (cropRange) {
1186 +                hdrRedValue = qMin(hdrRedValue, 1.0f);
1187 +            }
1188 +
1189 +            pxl[0] = floatToFloat16(hdrRedValue);
1190 +
1191 +            if (y > size / 2) {
1192 +                const float portion = (float(y) / size - 0.5f) * 2.0f;
1193 +                const float value = qMin(1.0f, 0.2f + 1.8f * portion);
1194 +
1195 +                pxl[1] = floatToFloat16(value);
1196 +                pxl[2] = floatToFloat16(value);
1197 +            } else {
1198 +                pxl[1] = floatToFloat16(0.2);
1199 +                pxl[2] = floatToFloat16(0.2);
1200 +            }
1201 +
1202 +            pxl[3] = floatToFloat16(1.0);
1203 +
1204 +            pixelPtr += 4;
1205 +        }
1206 +    }
1207 +
1208 +    return image;
1209 +}
1210 +
1211 +inline float linearToSRGB(float value)
1212 +{
1213 +    if (value <= 0.0f) {
1214 +        value = 0.0f;
1215 +    } else if (value < 0.0031308f) {
1216 +        value = value * 12.92f;
1217 +    } else if (value < 1.0f) {
1218 +        value = std::pow(value, 0.41666f) * 1.055f - 0.055f;
1219 +    } else {
1220 +        value = 1.0f;
1221 +    }
1222 +    return value;
1223 +}
1224 +
1225 +QImage Window::convertToQImage(const KisGLImageF16 &image) const
1226 +{
1227 +    const QSize size = image.size();
1228 +    const qfloat16 *pixelPtr = image.constData();
1229 +
1230 +    QImage qimage(size, QImage::Format_ARGB32);
1231 +    quint8 *qimagePixelPtr = qimage.bits();
1232 +
1233 +
1234 +    for (int y = 0; y < size.height(); y++) {
1235 +        for (int x = 0; x < size.width(); x++) {
1236 +            const qfloat16 *srcPxl = pixelPtr;
1237 +            quint8 *dstPxl = qimagePixelPtr;
1238 +
1239 +            auto convertChannel = [] (qfloat16 x) {
1240 +                float value = float16ToFloat(x);
1241 +                return quint8(linearToSRGB(value) * 255.0f);
1242 +            };
1243 +
1244 +            dstPxl[0] =  convertChannel(srcPxl[2]);
1245 +            dstPxl[1] =  convertChannel(srcPxl[1]);
1246 +            dstPxl[2] =  convertChannel(srcPxl[0]);
1247 +            dstPxl[3] =  convertChannel(srcPxl[3]);
1248 +
1249 +            pixelPtr += 4;
1250 +            qimagePixelPtr += 4;
1251 +        }
1252 +    }
1253 +
1254 +    return qimage;
1255 +}
1256 +
1257 +void Window::updateSurfaceInfo()
1258 +{
1259 +    const QSurfaceFormat format = m_imageWidget->context()->format();
1260 +
1261 +    m_lblContextInfo->setText(
1262 +        QString("renderer: %1\ncolorSpace: %2\n\n")
1263 +                .arg(format.renderableType() == QSurfaceFormat::OpenGL ? "openGL" : "openGL ES")
1264 +                .arg(format.colorSpace() == QSurfaceFormat::sRGBColorSpace ? "sRGB" :
1265 +                     format.colorSpace() == QSurfaceFormat::scRGBColorSpace ? "scRGB" :
1266 +                     format.colorSpace() == QSurfaceFormat::bt2020PQColorSpace ? "Bt. 2020 PQ" :
1267 +                     "unknown"));
1268 +}
1269 +
1270 +void Window::showEvent(QShowEvent *ev)
1271 +{
1272 +    QMainWindow::showEvent(ev);
1273 +
1274 +    if (m_lblContextInfo->text().isEmpty()) {
1275 +        updateSurfaceInfo();
1276 +    }
1277 +}
1278 diff --git a/tests/manual/hdr-qopenglwidget/window.h b/tests/manual/hdr-qopenglwidget/window.h
1279 new file mode 100644
1280 index 0000000000..fd8e5c0393
1281 --- /dev/null
1282 +++ b/tests/manual/hdr-qopenglwidget/window.h
1283 @@ -0,0 +1,69 @@
1284 +/****************************************************************************
1285 +**
1286 +** Copyright (C) 2019 The Qt Company Ltd.
1287 +** Contact: https://www.qt.io/licensing/
1288 +**
1289 +** This file is part of the test suite of the Qt Toolkit.
1290 +**
1291 +** $QT_BEGIN_LICENSE:GPL-EXCEPT$
1292 +** Commercial License Usage
1293 +** Licensees holding valid commercial Qt licenses may use this file in
1294 +** accordance with the commercial license agreement provided with the
1295 +** Software or, alternatively, in accordance with the terms contained in
1296 +** a written agreement between you and The Qt Company. For licensing terms
1297 +** and conditions see https://www.qt.io/terms-conditions. For further
1298 +** information use the contact form at https://www.qt.io/contact-us.
1299 +**
1300 +** GNU General Public License Usage
1301 +** Alternatively, this file may be used under the terms of the GNU
1302 +** General Public License version 3 as published by the Free Software
1303 +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
1304 +** included in the packaging of this file. Please review the following
1305 +** information to ensure the GNU General Public License requirements will
1306 +** be met: https://www.gnu.org/licenses/gpl-3.0.html.
1307 +**
1308 +** $QT_END_LICENSE$
1309 +**
1310 +****************************************************************************/
1311 +
1312 +#ifndef WINDOW_H
1313 +#define WINDOW_H
1314 +
1315 +#include <QMainWindow>
1316 +
1317 +class QAction;
1318 +
1319 +class GLWidget;
1320 +class KisGLImageWidget;
1321 +class KisGLImageF16;
1322 +class QLabel;
1323 +
1324 +class Window : public QMainWindow
1325 +{
1326 +    Q_OBJECT
1327 +
1328 +public:
1329 +    Window();
1330 +
1331 +    void showEvent(QShowEvent *ev) override;
1332 +
1333 +public Q_SLOTS:
1334 +
1335 +
1336 +private:
1337 +    KisGLImageF16 initializeImage(bool cropRange) const;
1338 +    QImage convertToQImage(const KisGLImageF16 &image) const;
1339 +
1340 +    void updateSurfaceInfo();
1341 +
1342 +private:
1343 +    GLWidget *m_glWidget {0};
1344 +    QAction *m_openAction {0};
1345 +    QAction *m_quitAction {0};
1346 +    KisGLImageWidget *m_imageWidget;
1347 +    KisGLImageWidget *m_imageWidgetSdr;
1348 +    QLabel *m_lblContextInfo;
1349 +
1350 +};
1351 +
1352 +#endif
1353 diff --git a/tests/manual/manual.pro b/tests/manual/manual.pro
1354 index ab00a5ef60..b202ed0431 100644
1355 --- a/tests/manual/manual.pro
1356 +++ b/tests/manual/manual.pro
1357 @@ -59,7 +59,7 @@ qtabbar
1358  
1359  qtConfig(opengl) {
1360      SUBDIRS += qopengltextureblitter
1361 -    qtConfig(egl): SUBDIRS += qopenglcontext
1362 +    qtConfig(egl): SUBDIRS += qopenglcontext hdr-qopenglwidget
1363  }
1364  
1365  win32: SUBDIRS -= network_remote_stresstest network_stresstest
1366 -- 
1367 2.20.1.windows.1
1368