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