Simplify and speed up OpenGL framebuffer grabbing.

If possible, let glReadPixels() itself provide the pixel format
that QImage requires, so we can drop the pixel manipulation afterwards.

Change-Id: I6c9226003c15d49548fa00696f31d0b2e26c0783
Reviewed-by: Samuel Rødal <samuel.rodal@digia.com>
This commit is contained in:
aavit 2012-11-06 09:26:09 +01:00 committed by The Qt Project
parent 89ccb0a699
commit 0d519164f2

View File

@ -1014,66 +1014,25 @@ QOpenGLFramebufferObjectFormat QOpenGLFramebufferObject::format() const
return d->format;
}
namespace {
/*
Read back the contents of the currently bound framebuffer, used in
QGLWidget::grabFrameBuffer(), QGLPixelbuffer::toImage() and
QGLFramebufferObject::toImage()
*/
void convertFromGLImage(QImage &img, int w, int h, bool alpha_format, bool include_alpha)
{
if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
// OpenGL gives RGBA; Qt wants ARGB
uint *p = (uint*)img.bits();
uint *end = p + w*h;
if (alpha_format && include_alpha) {
while (p < end) {
uint a = *p << 24;
*p = (*p >> 8) | a;
p++;
}
} else {
// This is an old legacy fix for PowerPC based Macs, which
// we shouldn't remove
while (p < end) {
*p = 0xff000000 | (*p>>8);
++p;
}
}
} else {
// OpenGL gives ABGR (i.e. RGBA backwards); Qt wants ARGB
for (int y = 0; y < h; y++) {
uint *q = (uint*)img.scanLine(y);
for (int x=0; x < w; ++x) {
const uint pixel = *q;
if (alpha_format && include_alpha) {
*q = ((pixel << 16) & 0xff0000) | ((pixel >> 16) & 0xff)
| (pixel & 0xff00ff00);
} else {
*q = 0xff000000 | ((pixel << 16) & 0xff0000)
| ((pixel >> 16) & 0xff) | (pixel & 0x00ff00);
}
q++;
}
}
}
img = img.mirrored();
}
}
Q_GUI_EXPORT QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_format, bool include_alpha)
{
QImage img(size, (alpha_format && include_alpha) ? QImage::Format_ARGB32_Premultiplied
: QImage::Format_RGB32);
int w = size.width();
int h = size.height();
glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, img.bits());
convertFromGLImage(img, w, h, alpha_format, include_alpha);
return img;
#ifdef QT_OPENGL_ES
GLint fmt = GL_BGRA_EXT;
#else
GLint fmt = GL_BGRA;
#endif
while (glGetError());
glReadPixels(0, 0, w, h, fmt, GL_UNSIGNED_BYTE, img.bits());
if (glGetError()) {
glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, img.bits());
img = img.rgbSwapped();
}
return img.mirrored();
}
/*!