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>
bb10
Samuel Rødal 2011-11-02 17:02:11 +01:00 committed by Qt by Nokia
parent 780a03191f
commit 171e137d25
3 changed files with 98 additions and 61 deletions

View File

@ -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;
}
}

View File

@ -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();
uint qt_pow_gamma[256];
uchar qt_pow_invgamma[2048];
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
}
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)

View File

@ -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;
}