Warning, /graphics/krita/3rdparty/ext_qt/0004-Implement-color-space-selection-for-QSurfaceFormat.patch is written in an unsupported language. File is not indexed.

0001 From 794065745b418e7dec64c165fe4c664035d8d5b4 Mon Sep 17 00:00:00 2001
0002 From: Dmitry Kazakov <dimula73@gmail.com>
0003 Date: Wed, 13 Feb 2019 16:56:11 +0300
0004 Subject: [PATCH 14/47] Implement color space selection for QSurfaceFormat
0005 
0006 With the patch one can select color space of openGL surface
0007 which is used a a root surface of the underlying native window.
0008 
0009 This feature is needed, e.g. when the user wants to render HDR
0010 content on screen. In such a case OS should be instructed about
0011 how to treat the graphical data in the application framebuffer.
0012 
0013 The easiest approach is to call QSurfaceFormat::setDefaultFormat()
0014 before creating the first application window. In such a case the
0015 root surface will (may) be in the requested format.
0016 
0017 Supported color spaces/formats:
0018 
0019 1) sRGB, SDR
0020 2) scRGB (Rec 709, gamma 1.0), HDR
0021 3) Rec 2020 PQ, HDR
0022 
0023 Please take into account that in real life the user should select
0024 proper bit depth for each color space, otherwise the system will
0025 refuse to create the surface:
0026 
0027 1) sRGB --- 8 bit or 10 bit
0028 2) scRGB --- 16 bit only
0029 3) Rec 2020 PQ --- 10 bit only
0030 
0031 Please note that color space selection is supported only on
0032 platforms with DXGI 1.4 and higher.
0033 
0034 Change-Id: I5f4945db9798d542f19c8ff1af1effa34f7745fd
0035 ---
0036  src/gui/kernel/qsurfaceformat.cpp             | 11 ++++
0037  src/gui/kernel/qsurfaceformat.h               |  4 +-
0038  src/gui/opengl/qopenglframebufferobject.cpp   |  7 ++-
0039  .../platforms/windows/qwindowseglcontext.cpp  | 57 +++++++++++++++++--
0040  .../platforms/windows/qwindowseglcontext.h    |  6 +-
0041  .../platforms/windows/qwindowsopenglcontext.h |  2 +-
0042  .../platforms/windows/qwindowswindow.cpp      |  8 ++-
0043  7 files changed, 83 insertions(+), 12 deletions(-)
0044 
0045 diff --git a/src/gui/kernel/qsurfaceformat.cpp b/src/gui/kernel/qsurfaceformat.cpp
0046 index 4e2bcad50f..d8e4c62ddc 100644
0047 --- a/src/gui/kernel/qsurfaceformat.cpp
0048 +++ b/src/gui/kernel/qsurfaceformat.cpp
0049 @@ -221,6 +221,17 @@ public:
0050      set, the window will be created with an sRGB-capable default
0051      framebuffer. Note that some platforms may return windows with a sRGB-capable
0052      default framebuffer even when not requested explicitly.
0053 +
0054 +    \value scRGBColorSpace When \c{EGL_EXT_gl_colorspace_scrgb_linear}
0055 +    is supported by the platform and this value is set, the window will
0056 +    be created with an scRGB-capable default framebuffer. Note that some
0057 +    platforms may return windows with a scRGB-capable default framebuffer
0058 +    even when not requested explicitly. It usually happens when the application
0059 +    requests 16-bit surface format.
0060 +
0061 +    \value bt2020PQColorSpace When \c{EGL_EXT_gl_colorspace_bt2020_pq}
0062 +    is supported by the platform and this value is set, the window will
0063 +    be created with an bt2020 PQ default framebuffer.
0064   */
0065  
0066  /*!
0067 diff --git a/src/gui/kernel/qsurfaceformat.h b/src/gui/kernel/qsurfaceformat.h
0068 index ed63eb8bbf..9ba6a29b7a 100644
0069 --- a/src/gui/kernel/qsurfaceformat.h
0070 +++ b/src/gui/kernel/qsurfaceformat.h
0071 @@ -87,7 +87,9 @@ public:
0072  
0073      enum ColorSpace {
0074          DefaultColorSpace,
0075 -        sRGBColorSpace
0076 +        sRGBColorSpace,
0077 +        scRGBColorSpace,
0078 +        bt2020PQColorSpace
0079      };
0080      Q_ENUM(ColorSpace)
0081  
0082 diff --git a/src/gui/opengl/qopenglframebufferobject.cpp b/src/gui/opengl/qopenglframebufferobject.cpp
0083 index cae3d516c4..ccdccb637a 100644
0084 --- a/src/gui/opengl/qopenglframebufferobject.cpp
0085 +++ b/src/gui/opengl/qopenglframebufferobject.cpp
0086 @@ -545,10 +545,13 @@ void QOpenGLFramebufferObjectPrivate::initTexture(int idx)
0087      ColorAttachment &color(colorAttachments[idx]);
0088  
0089      GLuint pixelType = GL_UNSIGNED_BYTE;
0090 -    if (color.internalFormat == GL_RGB10_A2 || color.internalFormat == GL_RGB10)
0091 +    if (color.internalFormat == GL_RGB10_A2 || color.internalFormat == GL_RGB10) {
0092          pixelType = GL_UNSIGNED_INT_2_10_10_10_REV;
0093 -    else if (color.internalFormat == GL_RGB16  || color.internalFormat == GL_RGBA16)
0094 +    } else if (color.internalFormat == GL_RGB16  || color.internalFormat == GL_RGBA16) {
0095          pixelType = GL_UNSIGNED_SHORT;
0096 +    } else if (color.internalFormat == GL_RGBA16F) {
0097 +        pixelType = GL_HALF_FLOAT;
0098 +    }
0099  
0100      funcs.glTexImage2D(target, 0, color.internalFormat, color.size.width(), color.size.height(), 0,
0101                         GL_RGBA, pixelType, NULL);
0102 diff --git a/src/plugins/platforms/windows/qwindowseglcontext.cpp b/src/plugins/platforms/windows/qwindowseglcontext.cpp
0103 index 063e81150e..4cd745eac6 100644
0104 --- a/src/plugins/platforms/windows/qwindowseglcontext.cpp
0105 +++ b/src/plugins/platforms/windows/qwindowseglcontext.cpp
0106 @@ -151,8 +151,9 @@ bool QWindowsLibEGL::init()
0107      eglGetCurrentDisplay = RESOLVE((EGLDisplay (EGLAPIENTRY *)(void)), eglGetCurrentDisplay);
0108      eglSwapBuffers = RESOLVE((EGLBoolean (EGLAPIENTRY *)(EGLDisplay , EGLSurface)), eglSwapBuffers);
0109      eglGetProcAddress = RESOLVE((QFunctionPointer (EGLAPIENTRY * )(const char *)), eglGetProcAddress);
0110 +    eglQueryString = RESOLVE((const char* (EGLAPIENTRY *)(EGLDisplay, EGLint)), eglQueryString);
0111  
0112 -    if (!eglGetError || !eglGetDisplay || !eglInitialize || !eglGetProcAddress)
0113 +    if (!eglGetError || !eglGetDisplay || !eglInitialize || !eglGetProcAddress || !eglQueryString)
0114          return false;
0115  
0116      eglGetPlatformDisplayEXT = nullptr;
0117 @@ -197,8 +198,15 @@ bool QWindowsLibGLESv2::init()
0118  }
0119  
0120  QWindowsEGLStaticContext::QWindowsEGLStaticContext(EGLDisplay display)
0121 -    : m_display(display)
0122 +    : m_display(display),
0123 +      m_hasSRGBColorSpaceSupport(false),
0124 +      m_hasSCRGBColorSpaceSupport(false),
0125 +      m_hasBt2020PQColorSpaceSupport(false)
0126  {
0127 +    const char *eglExtensions = libEGL.eglQueryString(display, EGL_EXTENSIONS);
0128 +    m_hasSRGBColorSpaceSupport = strstr(eglExtensions, "EGL_KHR_gl_colorspace") != nullptr;
0129 +    m_hasSCRGBColorSpaceSupport = strstr(eglExtensions, "EGL_EXT_gl_colorspace_scrgb_linear") != nullptr;
0130 +    m_hasBt2020PQColorSpaceSupport = strstr(eglExtensions, "EGL_EXT_gl_colorspace_bt2020_pq") != nullptr;
0131  }
0132  
0133  bool QWindowsEGLStaticContext::initializeAngle(QWindowsOpenGLTester::Renderers preferredType, HDC dc,
0134 @@ -297,11 +305,48 @@ QWindowsOpenGLContext *QWindowsEGLStaticContext::createContext(QOpenGLContext *c
0135      return new QWindowsEGLContext(this, context->format(), context->shareHandle());
0136  }
0137  
0138 -void *QWindowsEGLStaticContext::createWindowSurface(void *nativeWindow, void *nativeConfig, int *err)
0139 +void *QWindowsEGLStaticContext::createWindowSurface(void *nativeWindow, void *nativeConfig,
0140 +                                                    QSurfaceFormat::ColorSpace colorSpace, int *err)
0141  {
0142      *err = 0;
0143 +
0144 +    EGLint eglColorSpace = EGL_GL_COLORSPACE_LINEAR_KHR;
0145 +    bool colorSpaceSupported = false;
0146 +
0147 +    switch (colorSpace) {
0148 +    case QSurfaceFormat::DefaultColorSpace:
0149 +        colorSpaceSupported = m_hasSRGBColorSpaceSupport;
0150 +        break;
0151 +    case QSurfaceFormat::sRGBColorSpace:
0152 +        eglColorSpace = EGL_GL_COLORSPACE_SRGB_KHR;
0153 +        colorSpaceSupported = m_hasSRGBColorSpaceSupport;
0154 +        break;
0155 +    case QSurfaceFormat::scRGBColorSpace:
0156 +        eglColorSpace = EGL_GL_COLORSPACE_SCRGB_LINEAR_EXT;
0157 +        colorSpaceSupported = m_hasSCRGBColorSpaceSupport;
0158 +        break;
0159 +    case QSurfaceFormat::bt2020PQColorSpace:
0160 +        eglColorSpace = EGL_GL_COLORSPACE_BT2020_PQ_EXT;
0161 +        colorSpaceSupported = m_hasBt2020PQColorSpaceSupport;
0162 +        break;
0163 +    }
0164 +
0165 +    QVector<EGLint> attributes;
0166 +
0167 +    if (colorSpaceSupported) {
0168 +        attributes << EGL_GL_COLORSPACE << eglColorSpace;
0169 +    }
0170 +
0171 +    attributes << EGL_NONE;
0172 +
0173 +    if (!colorSpaceSupported && colorSpace != QSurfaceFormat::DefaultColorSpace) {
0174 +        qWarning().nospace() << __FUNCTION__ << ": Requested color space is not supported by EGL implementation: " << colorSpace << " (egl: 0x" << hex << eglColorSpace << ")";
0175 +    }
0176 +
0177 +
0178      EGLSurface surface = libEGL.eglCreateWindowSurface(m_display, nativeConfig,
0179 -                                                       static_cast<EGLNativeWindowType>(nativeWindow), nullptr);
0180 +                                                       static_cast<EGLNativeWindowType>(nativeWindow),
0181 +                                                       attributes.constData());
0182      if (surface == EGL_NO_SURFACE) {
0183          *err = libEGL.eglGetError();
0184          qWarning("%s: Could not create the EGL window surface: 0x%x", __FUNCTION__, *err);
0185 @@ -349,6 +394,7 @@ QSurfaceFormat QWindowsEGLStaticContext::formatFromConfig(EGLDisplay display, EG
0186      format.setSamples(sampleCount);
0187      format.setStereo(false);
0188      format.setSwapInterval(referenceFormat.swapInterval());
0189 +    format.setColorSpace(referenceFormat.colorSpace());
0190  
0191      // Clear the EGL error state because some of the above may
0192      // have errored out because the attribute is not applicable
0193 @@ -378,7 +424,6 @@ QSurfaceFormat QWindowsEGLStaticContext::formatFromConfig(EGLDisplay display, EG
0194      \internal
0195      \ingroup qt-lighthouse-win
0196  */
0197 -
0198  QWindowsEGLContext::QWindowsEGLContext(QWindowsEGLStaticContext *staticContext,
0199                                         const QSurfaceFormat &format,
0200                                         QPlatformOpenGLContext *share)
0201 @@ -483,6 +528,8 @@ bool QWindowsEGLContext::makeCurrent(QPlatformSurface *surface)
0202              // Simulate context loss as the context is useless.
0203              QWindowsEGLStaticContext::libEGL.eglDestroyContext(m_eglDisplay, m_eglContext);
0204              m_eglContext = EGL_NO_CONTEXT;
0205 +        } else if (err == EGL_BAD_MATCH) {
0206 +            qCDebug(lcQpaGl) << "Got bad match in createWindowSurface() for context" << this << "Check color space configuration.";
0207          }
0208          return false;
0209      }
0210 diff --git a/src/plugins/platforms/windows/qwindowseglcontext.h b/src/plugins/platforms/windows/qwindowseglcontext.h
0211 index 8a1e1ddae8..9f7742e6fb 100644
0212 --- a/src/plugins/platforms/windows/qwindowseglcontext.h
0213 +++ b/src/plugins/platforms/windows/qwindowseglcontext.h
0214 @@ -80,6 +80,7 @@ struct QWindowsLibEGL
0215      QFunctionPointer (EGLAPIENTRY *eglGetProcAddress)(const char *procname);
0216  
0217      EGLDisplay (EGLAPIENTRY * eglGetPlatformDisplayEXT)(EGLenum platform, void *native_display, const EGLint *attrib_list);
0218 +    const char* (EGLAPIENTRY * eglQueryString)(EGLDisplay dpy, EGLint name);
0219  
0220  private:
0221  #if !defined(QT_STATIC) || defined(QT_OPENGL_DYNAMIC)
0222 @@ -121,7 +122,7 @@ public:
0223      void *moduleHandle() const override { return libGLESv2.moduleHandle(); }
0224      QOpenGLContext::OpenGLModuleType moduleType() const override { return QOpenGLContext::LibGLES; }
0225  
0226 -    void *createWindowSurface(void *nativeWindow, void *nativeConfig, int *err) override;
0227 +    void *createWindowSurface(void *nativeWindow, void *nativeConfig, QSurfaceFormat::ColorSpace colorSpace, int *err) override;
0228      void destroyWindowSurface(void *nativeSurface) override;
0229  
0230      QSurfaceFormat formatFromConfig(EGLDisplay display, EGLConfig config, const QSurfaceFormat &referenceFormat);
0231 @@ -135,6 +136,9 @@ private:
0232                                  EGLDisplay *display, EGLint *major, EGLint *minor);
0233  
0234      const EGLDisplay m_display;
0235 +    bool m_hasSRGBColorSpaceSupport;
0236 +    bool m_hasSCRGBColorSpaceSupport;
0237 +    bool m_hasBt2020PQColorSpaceSupport;
0238  };
0239  
0240  class QWindowsEGLContext : public QWindowsOpenGLContext
0241 diff --git a/src/plugins/platforms/windows/qwindowsopenglcontext.h b/src/plugins/platforms/windows/qwindowsopenglcontext.h
0242 index cc6d93d35e..61c0e28767 100644
0243 --- a/src/plugins/platforms/windows/qwindowsopenglcontext.h
0244 +++ b/src/plugins/platforms/windows/qwindowsopenglcontext.h
0245 @@ -63,7 +63,7 @@ public:
0246  
0247      // If the windowing system interface needs explicitly created window surfaces (like EGL),
0248      // reimplement these.
0249 -    virtual void *createWindowSurface(void * /*nativeWindow*/, void * /*nativeConfig*/, int * /*err*/) { return 0; }
0250 +    virtual void *createWindowSurface(void * /*nativeWindow*/, void * /*nativeConfig*/, QSurfaceFormat::ColorSpace /*colorSpace*/, int * /*err*/) { return 0; }
0251      virtual void destroyWindowSurface(void * /*nativeSurface*/) { }
0252  
0253  protected:
0254 diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp
0255 index adf0f918ca..394486073a 100644
0256 --- a/src/plugins/platforms/windows/qwindowswindow.cpp
0257 +++ b/src/plugins/platforms/windows/qwindowswindow.cpp
0258 @@ -2883,9 +2883,13 @@ void *QWindowsWindow::surface(void *nativeConfig, int *err)
0259      return 0;
0260  #endif
0261  #ifndef QT_NO_OPENGL
0262 +
0263 +
0264 +
0265      if (!m_surface) {
0266 -        if (QWindowsStaticOpenGLContext *staticOpenGLContext = QWindowsIntegration::staticOpenGLContext())
0267 -            m_surface = staticOpenGLContext->createWindowSurface(m_data.hwnd, nativeConfig, err);
0268 +        if (QWindowsStaticOpenGLContext *staticOpenGLContext = QWindowsIntegration::staticOpenGLContext()) {
0269 +            m_surface = staticOpenGLContext->createWindowSurface(m_data.hwnd, nativeConfig, m_format.colorSpace(), err);
0270 +        }
0271      }
0272  
0273      return m_surface;
0274 -- 
0275 2.20.1.windows.1
0276