Simplify and speed up OpenGL framebuffer grabbing.
authoraavit <eirik.aavitsland@digia.com>
Tue, 6 Nov 2012 08:26:09 +0000 (09:26 +0100)
committerThe Qt Project <gerrit-noreply@qt-project.org>
Thu, 8 Nov 2012 23:37:42 +0000 (00:37 +0100)
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>
src/gui/opengl/qopenglframebufferobject.cpp

index 380ada3..1e0a9e0 100644 (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();
 }
 
 /*!