diff options
author | Samuel Rødal <samuel.rodal@nokia.com> | 2011-11-02 17:02:11 +0100 |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2011-11-04 14:31:25 +0100 |
commit | 171e137d25dccca15b31e6bd01de58776f3d9e94 (patch) | |
tree | f94b10cbaa65b18c32b199b315e0b27763bec534 | |
parent | 780a03191feb2b5f64de97ad623ad9e0c4f5871a (diff) |
Improve QtGui start-up time and memory use.
The gamma lookup tables can be allocated and computed on demand, as
they're not always needed, depending on the platform and the use case.
Change-Id: I2d4c2860746366a0e46edb53bd4ecd2778de2464
Reviewed-by: Olivier Goffart <ogoffart@kde.org>
-rw-r--r-- | src/gui/image/qimage.cpp | 12 | ||||
-rw-r--r-- | src/gui/painting/qdrawhelper.cpp | 141 | ||||
-rw-r--r-- | src/gui/text/qfontenginedirectwrite.cpp | 6 |
3 files changed, 98 insertions, 61 deletions
diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp index a19b608216..c107fea919 100644 --- a/src/gui/image/qimage.cpp +++ b/src/gui/image/qimage.cpp @@ -3340,9 +3340,13 @@ void qInitImageConversions() #endif } +extern const uchar *qt_pow_rgb_gamma(); + void qGamma_correct_back_to_linear_cs(QImage *image) { - extern uchar qt_pow_rgb_gamma[256]; + const uchar *gamma = qt_pow_rgb_gamma(); + if (!gamma) + return; // gamma correct the pixels back to linear color space... int h = image->height(); @@ -3352,9 +3356,9 @@ void qGamma_correct_back_to_linear_cs(QImage *image) uint *pixels = (uint *) image->scanLine(y); for (int x=0; x<w; ++x) { uint p = pixels[x]; - uint r = qt_pow_rgb_gamma[qRed(p)]; - uint g = qt_pow_rgb_gamma[qGreen(p)]; - uint b = qt_pow_rgb_gamma[qBlue(p)]; + uint r = gamma[qRed(p)]; + uint g = gamma[qGreen(p)]; + uint b = gamma[qBlue(p)]; pixels[x] = (r << 16) | (g << 8) | b | 0xff000000; } } diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp index 88c237b59b..cf899b986d 100644 --- a/src/gui/painting/qdrawhelper.cpp +++ b/src/gui/painting/qdrawhelper.cpp @@ -6519,11 +6519,52 @@ inline static void qt_bitmapblit_quint16(QRasterBuffer *rasterBuffer, } -uchar qt_pow_rgb_gamma[256]; -uchar qt_pow_rgb_invgamma[256]; +struct QDrawHelperGammaTables +{ + QDrawHelperGammaTables(); + + uchar qt_pow_rgb_gamma[256]; + uchar qt_pow_rgb_invgamma[256]; + +#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) + uint qt_pow_gamma[256]; + uchar qt_pow_invgamma[2048]; +#endif +}; + +QDrawHelperGammaTables::QDrawHelperGammaTables() +{ + qreal smoothing = qreal(1.7); + + for (int i=0; i<256; ++i) { + qt_pow_rgb_gamma[i] = uchar(qRound(qPow(i / qreal(255.0), smoothing) * 255)); + qt_pow_rgb_invgamma[i] = uchar(qRound(qPow(i / qreal(255.), 1 / smoothing) * 255)); + } + +#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) + const qreal gray_gamma = 2.31; + for (int i=0; i<256; ++i) + qt_pow_gamma[i] = uint(qRound(qPow(i / qreal(255.), gray_gamma) * 2047)); + for (int i=0; i<2048; ++i) + qt_pow_invgamma[i] = uchar(qRound(qPow(i / qreal(2047.0), 1 / gray_gamma) * 255)); +#endif +} -uint qt_pow_gamma[256]; -uchar qt_pow_invgamma[2048]; +Q_GLOBAL_STATIC(QDrawHelperGammaTables, qt_gamma_tables); + +#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) +const uint *qt_pow_gamma() +{ + QDrawHelperGammaTables *tables = qt_gamma_tables(); + return tables ? tables->qt_pow_gamma : 0; +} +#endif + +const uchar *qt_pow_rgb_gamma() +{ + QDrawHelperGammaTables *tables = qt_gamma_tables(); + return tables ? tables->qt_pow_rgb_gamma : 0; +} static void qt_alphamapblit_quint16(QRasterBuffer *rasterBuffer, int x, int y, quint32 color, @@ -6554,26 +6595,7 @@ static void qt_alphamapblit_quint16(QRasterBuffer *rasterBuffer, } } -void qt_build_pow_tables() { - qreal smoothing = qreal(1.7); - - - - for (int i=0; i<256; ++i) { - qt_pow_rgb_gamma[i] = uchar(qRound(qPow(i / qreal(255.0), smoothing) * 255)); - qt_pow_rgb_invgamma[i] = uchar(qRound(qPow(i / qreal(255.), 1 / smoothing) * 255)); - } - -#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) - const qreal gray_gamma = 2.31; - for (int i=0; i<256; ++i) - qt_pow_gamma[i] = uint(qRound(qPow(i / qreal(255.), gray_gamma) * 2047)); - for (int i=0; i<2048; ++i) - qt_pow_invgamma[i] = uchar(qRound(qPow(i / qreal(2047.0), 1 / gray_gamma) * 255)); -#endif -} - -static inline void rgbBlendPixel(quint32 *dst, int coverage, int sr, int sg, int sb) +static inline void rgbBlendPixel(quint32 *dst, int coverage, int sr, int sg, int sb, const uchar *gamma, const uchar *invgamma) { // Do a gray alphablend... int da = qAlpha(*dst); @@ -6585,9 +6607,9 @@ static inline void rgbBlendPixel(quint32 *dst, int coverage, int sr, int sg, int ) { int a = qGray(coverage); - sr = qt_div_255(qt_pow_rgb_invgamma[sr] * a); - sg = qt_div_255(qt_pow_rgb_invgamma[sg] * a); - sb = qt_div_255(qt_pow_rgb_invgamma[sb] * a); + sr = qt_div_255(invgamma[sr] * a); + sg = qt_div_255(invgamma[sg] * a); + sb = qt_div_255(invgamma[sb] * a); int ia = 255 - a; dr = qt_div_255(dr * ia); @@ -6605,32 +6627,32 @@ static inline void rgbBlendPixel(quint32 *dst, int coverage, int sr, int sg, int int mg = qGreen(coverage); int mb = qBlue(coverage); - dr = qt_pow_rgb_gamma[dr]; - dg = qt_pow_rgb_gamma[dg]; - db = qt_pow_rgb_gamma[db]; + dr = gamma[dr]; + dg = gamma[dg]; + db = gamma[db]; int nr = qt_div_255((sr - dr) * mr) + dr; int ng = qt_div_255((sg - dg) * mg) + dg; int nb = qt_div_255((sb - db) * mb) + db; - nr = qt_pow_rgb_invgamma[nr]; - ng = qt_pow_rgb_invgamma[ng]; - nb = qt_pow_rgb_invgamma[nb]; + nr = invgamma[nr]; + ng = invgamma[ng]; + nb = invgamma[nb]; *dst = qRgb(nr, ng, nb); } #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) -static inline void grayBlendPixel(quint32 *dst, int coverage, int sr, int sg, int sb) +static inline void grayBlendPixel(quint32 *dst, int coverage, int sr, int sg, int sb, const uint *gamma, const uchar *invgamma) { // Do a gammacorrected gray alphablend... int dr = qRed(*dst); int dg = qGreen(*dst); int db = qBlue(*dst); - dr = qt_pow_gamma[dr]; - dg = qt_pow_gamma[dg]; - db = qt_pow_gamma[db]; + dr = gamma[dr]; + dg = gamma[dg]; + db = gamma[db]; int alpha = coverage; int ialpha = 255 - alpha; @@ -6638,9 +6660,9 @@ static inline void grayBlendPixel(quint32 *dst, int coverage, int sr, int sg, in int ng = (sg * alpha + ialpha * dg) / 255; int nb = (sb * alpha + ialpha * db) / 255; - nr = qt_pow_invgamma[nr]; - ng = qt_pow_invgamma[ng]; - nb = qt_pow_invgamma[nb]; + nr = invgamma[nr]; + ng = invgamma[ng]; + nb = invgamma[nb]; *dst = qRgb(nr, ng, nb); } @@ -6656,13 +6678,17 @@ static void qt_alphamapblit_quint32(QRasterBuffer *rasterBuffer, const int destStride = rasterBuffer->bytesPerLine() / sizeof(quint32); #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) - int sr = qRed(color); - int sg = qGreen(color); - int sb = qBlue(color); + QDrawHelperGammaTables *tables = qt_gamma_tables(); + if (!tables) + return; + + const uint *gamma = tables->qt_pow_gamma; + const uchar *invgamma = tables->qt_pow_invgamma; + + int sr = gamma[qRed(color)]; + int sg = gamma[qGreen(color)]; + int sb = gamma[qBlue(color)]; - sr = qt_pow_gamma[sr]; - sg = qt_pow_gamma[sg]; - sb = qt_pow_gamma[sb]; bool opaque_src = (qAlpha(color) == 255); #endif @@ -6680,7 +6706,7 @@ static void qt_alphamapblit_quint32(QRasterBuffer *rasterBuffer, #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) if (QSysInfo::WindowsVersion >= QSysInfo::WV_XP && opaque_src && qAlpha(dest[i]) == 255) { - grayBlendPixel(dest+i, coverage, sr, sg, sb); + grayBlendPixel(dest+i, coverage, sr, sg, sb, gamma, invgamma); } else #endif { @@ -6721,7 +6747,7 @@ static void qt_alphamapblit_quint32(QRasterBuffer *rasterBuffer, #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) if (QSysInfo::WindowsVersion >= QSysInfo::WV_XP && opaque_src && qAlpha(dest[xp]) == 255) { - grayBlendPixel(dest+xp, coverage, sr, sg, sb); + grayBlendPixel(dest+xp, coverage, sr, sg, sb, gamma, invgamma); } else #endif { @@ -6749,9 +6775,16 @@ static void qt_alphargbblit_quint32(QRasterBuffer *rasterBuffer, int sb = qBlue(color); int sa = qAlpha(color); - sr = qt_pow_rgb_gamma[sr]; - sg = qt_pow_rgb_gamma[sg]; - sb = qt_pow_rgb_gamma[sb]; + QDrawHelperGammaTables *tables = qt_gamma_tables(); + if (!tables) + return; + + const uchar *gamma = tables->qt_pow_rgb_gamma; + const uchar *invgamma = tables->qt_pow_rgb_invgamma; + + sr = gamma[sr]; + sg = gamma[sg]; + sb = gamma[sb]; if (sa == 0) return; @@ -6765,7 +6798,7 @@ static void qt_alphargbblit_quint32(QRasterBuffer *rasterBuffer, if (coverage == 0xffffffff) { dst[i] = c; } else if (coverage != 0xff000000) { - rgbBlendPixel(dst+i, coverage, sr, sg, sb); + rgbBlendPixel(dst+i, coverage, sr, sg, sb, gamma, invgamma); } } @@ -6795,7 +6828,7 @@ static void qt_alphargbblit_quint32(QRasterBuffer *rasterBuffer, if (coverage == 0xffffffff) { dst[xp] = c; } else if (coverage != 0xff000000) { - rgbBlendPixel(dst+xp, coverage, sr, sg, sb); + rgbBlendPixel(dst+xp, coverage, sr, sg, sb, gamma, invgamma); } } } // for (i -> line.count) @@ -7257,8 +7290,6 @@ void qInitDrawhelperAsm() } if (functionForModeAsm) functionForMode = functionForModeAsm; - - qt_build_pow_tables(); } static void qt_memfill32_setup(quint32 *dest, quint32 value, int count) diff --git a/src/gui/text/qfontenginedirectwrite.cpp b/src/gui/text/qfontenginedirectwrite.cpp index 5bac1172fa..952e06d151 100644 --- a/src/gui/text/qfontenginedirectwrite.cpp +++ b/src/gui/text/qfontenginedirectwrite.cpp @@ -508,7 +508,7 @@ qreal QFontEngineDirectWrite::maxCharWidth() const return 0; } -extern uint qt_pow_gamma[256]; +extern const uint *qt_pow_gamma(); QImage QFontEngineDirectWrite::alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &xform) @@ -521,11 +521,13 @@ QImage QFontEngineDirectWrite::alphaMapForGlyph(glyph_t glyph, QFixed subPixelPo colors[i] = qRgba(0, 0, 0, i); indexed.setColorTable(colors); + uint *gamma = qt_pow_gamma(); for (int y=0; y<im.height(); ++y) { uint *src = (uint*) im.scanLine(y); uchar *dst = indexed.scanLine(y); for (int x=0; x<im.width(); ++x) { - *dst = 255 - (qt_pow_gamma[qGray(0xffffffff - *src)] * 255. / 2047.); + uint gray = qGray(0xffffffff - *src); + *dst = 255 - (gamma ? gamma[gray] * 255. / 2047. : gray); ++dst; ++src; } |