From e443d8850105549eb1d72f54d3bf0d3d72cf90c2 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Tue, 3 May 2011 15:06:13 +0200 Subject: Support gamma correction of text on GL If the SRGB framebuffer extension in GL is available, we can support gamma correction of text with a gamma of 2.1. On Mac this is sufficient for gamma correcting subpixel antialiased text. Gray antialiasing should not be gamma corrected on Mac. On Windows, the user can potentially set the gamma value to anything between 1.0 and 2.2 (or something like that). We support anything that resembles 1.0 closely enough by pushing the text out without any correction (like before). We also support anything that resembles 2.1 (the gamma hardcoded in GL's SRGB extension) by turning on the extension before blending the text. In between the two, we'll use gray antialiasing to avoid differing too much from the raster engine (which is our reference in this.) For gray antialiasing on Windows, we use a constant gamma of 2.3 which has been determined by experimentation. Since this is close enough to 2.1 we do gamma correction with SRGB extension. The distance limit of 0.2 is determined by some experimentation. Reviewed-by: Samuel (cherry picked from commit 79ba7cceca5e4029876ace2121edd25b08ae14ce) --- src/gui/kernel/qapplication_win.cpp | 13 ++++++++- src/gui/painting/qdrawhelper.cpp | 10 ++----- .../gl2paintengineex/qpaintengineex_opengl2.cpp | 31 ++++++++++++++++++++-- src/opengl/qgl.cpp | 7 +++++ src/opengl/qgl_p.h | 3 ++- src/opengl/qglextensions_p.h | 8 ++++++ 6 files changed, 60 insertions(+), 12 deletions(-) diff --git a/src/gui/kernel/qapplication_win.cpp b/src/gui/kernel/qapplication_win.cpp index 0a03397251..1a490c9979 100644 --- a/src/gui/kernel/qapplication_win.cpp +++ b/src/gui/kernel/qapplication_win.cpp @@ -237,6 +237,7 @@ static void resolveAygLibs() # define FE_FONTSMOOTHINGCLEARTYPE 0x0002 #endif +Q_GUI_EXPORT qreal qt_fontsmoothing_gamma; Q_GUI_EXPORT bool qt_cleartype_enabled; Q_GUI_EXPORT bool qt_win_owndc_required; // CS_OWNDC is required if we use the GL graphicssystem as default @@ -653,8 +654,18 @@ static void qt_win_read_cleartype_settings() if (SystemParametersInfo(SPI_GETFONTSMOOTHINGTYPE, 0, &result, 0)) qt_cleartype_enabled = (result == FE_FONTSMOOTHINGCLEARTYPE); #endif -} + int winSmooth; + if (SystemParametersInfo(SPI_GETFONTSMOOTHINGCONTRAST, 0, &winSmooth, 0)) { + qt_fontsmoothing_gamma = winSmooth / qreal(1000.0); + } else { + qt_fontsmoothing_gamma = 1.0; + } + + // Safeguard ourselves against corrupt registry values... + if (qt_fontsmoothing_gamma > 5 || qt_fontsmoothing_gamma < 1) + qt_fontsmoothing_gamma = qreal(1.4); +} static void qt_set_windows_resources() { diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp index 5e75e4a884..3553b6064d 100644 --- a/src/gui/painting/qdrawhelper.cpp +++ b/src/gui/painting/qdrawhelper.cpp @@ -7198,14 +7198,8 @@ void qt_build_pow_tables() { #endif #ifdef Q_WS_WIN - int winSmooth; - if (SystemParametersInfo(0x200C /* SPI_GETFONTSMOOTHINGCONTRAST */, 0, &winSmooth, 0)) - smoothing = winSmooth / qreal(1000.0); - - // Safeguard ourselves against corrupt registry values... - if (smoothing > 5 || smoothing < 1) - smoothing = qreal(1.4); - + extern qreal qt_fontsmoothing_gamma; // qapplication_win.cpp + smoothing = qt_fontsmoothing_gamma; #endif #ifdef Q_WS_X11 diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index 18c684ff1b..673f614c0d 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -1548,6 +1548,14 @@ namespace { } +#if defined(Q_WS_WIN) +static bool fontSmoothingApproximately(qreal target) +{ + extern Q_GUI_EXPORT qreal qt_fontsmoothing_gamma; // qapplication_win.cpp + return (qAbs(qt_fontsmoothing_gamma - target) < 0.2); +} +#endif + // #define QT_OPENGL_DRAWCACHEDGLYPHS_INDEX_ARRAY_VBO void QGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type glyphType, @@ -1786,7 +1794,6 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type glyp shaderManager->setMaskType(QGLEngineShaderManager::PixelMask); prepareForDraw(false); // Text always causes src pixels to be transparent } - //### TODO: Gamma correction QGLTextureGlyphCache::FilterMode filterMode = (s->matrix.type() > QTransform::TxTranslate)?QGLTextureGlyphCache::Linear:QGLTextureGlyphCache::Nearest; if (lastMaskTextureUsed != cache->texture() || cache->filterMode() != filterMode) { @@ -1809,12 +1816,31 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type glyp } } + bool srgbFrameBufferEnabled = false; + if (ctx->d_ptr->extension_flags & QGLExtensions::SRGBFrameBuffer) { +#if defined(Q_WS_MAC) + if (glyphType == QFontEngineGlyphCache::Raster_RGBMask) +#elif defined(Q_WS_WIN) + if (glyphType != QFontEngineGlyphCache::Raster_RGBMask || fontSmoothingApproximately(2.1)) +#else + if (false) +#endif + { + glEnable(FRAMEBUFFER_SRGB_EXT); + srgbFrameBufferEnabled = true; + } + } + #if defined(QT_OPENGL_DRAWCACHEDGLYPHS_INDEX_ARRAY_VBO) glDrawElements(GL_TRIANGLE_STRIP, 6 * numGlyphs, GL_UNSIGNED_SHORT, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); #else glDrawElements(GL_TRIANGLE_STRIP, 6 * numGlyphs, GL_UNSIGNED_SHORT, elementIndices.data()); #endif + + if (srgbFrameBufferEnabled) + glDisable(FRAMEBUFFER_SRGB_EXT); + } void QGL2PaintEngineEx::drawPixmapFragments(const QPainter::PixmapFragment *fragments, int fragmentCount, const QPixmap &pixmap, @@ -1986,7 +2012,8 @@ bool QGL2PaintEngineEx::begin(QPaintDevice *pdev) #if !defined(QT_OPENGL_ES_2) #if defined(Q_WS_WIN) - if (qt_cleartype_enabled) + if (qt_cleartype_enabled + && (fontSmoothingApproximately(1.0) || fontSmoothingApproximately(2.1))) #endif #if defined(Q_WS_MAC) if (qt_applefontsmoothing_enabled) diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp index 7ce35f8d1c..4cb976f3c2 100644 --- a/src/opengl/qgl.cpp +++ b/src/opengl/qgl.cpp @@ -5521,6 +5521,13 @@ QGLExtensions::Extensions QGLExtensions::currentContextExtensions() if (extensions.match("GL_EXT_bgra")) glExtensions |= BGRATextureFormat; + { + GLboolean srgbCapableFramebuffers; + glGetBooleanv(FRAMEBUFFER_SRGB_CAPABLE_EXT, &srgbCapableFramebuffers); + if (srgbCapableFramebuffers) + glExtensions |= SRGBFrameBuffer; + } + return glExtensions; } diff --git a/src/opengl/qgl_p.h b/src/opengl/qgl_p.h index 6a503fab90..46683c742e 100644 --- a/src/opengl/qgl_p.h +++ b/src/opengl/qgl_p.h @@ -288,7 +288,8 @@ public: PVRTCTextureCompression = 0x00020000, FragmentShader = 0x00040000, ElementIndexUint = 0x00080000, - Depth24 = 0x00100000 + Depth24 = 0x00100000, + SRGBFrameBuffer = 0x00200000 }; Q_DECLARE_FLAGS(Extensions, Extension) diff --git a/src/opengl/qglextensions_p.h b/src/opengl/qglextensions_p.h index 529c7a1b4e..ac80ce8b96 100644 --- a/src/opengl/qglextensions_p.h +++ b/src/opengl/qglextensions_p.h @@ -477,6 +477,14 @@ struct QGLExtensionFuncs // OpenGL constants +#ifndef FRAMEBUFFER_SRGB_CAPABLE_EXT +#define FRAMEBUFFER_SRGB_CAPABLE_EXT 0x8DBA +#endif + +#ifndef FRAMEBUFFER_SRGB_EXT +#define FRAMEBUFFER_SRGB_EXT 0x8DB9 +#endif + #ifndef GL_ARRAY_BUFFER #define GL_ARRAY_BUFFER 0x8892 #endif -- cgit v1.2.3