Calling glReadPixels with BGRA format on an NVIDIA machine with an opaque context...
authorroger_fong@apple.com <roger_fong@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 18 Oct 2014 00:25:08 +0000 (00:25 +0000)
committerroger_fong@apple.com <roger_fong@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 18 Oct 2014 00:25:08 +0000 (00:25 +0000)
https://bugs.webkit.org/show_bug.cgi?id=137793.
<rdar://problem/15408133>

Reviewed by Dean Jackson.

This fixes conformance test context/context-attribute-preserve-drawing-buffer.html.

* platform/graphics/opengl/GraphicsContext3DOpenGL.cpp:
(WebCore::GraphicsContext3D::readPixelsAndConvertToBGRAIfNecessary):
On an NVIDIA machine, when the context has alpha turned off, call glReadPixels with RGBA format and then convert to RGBA.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@174855 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebCore/ChangeLog
Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGL.cpp

index 11788cc..97d18a7 100644 (file)
@@ -1,3 +1,17 @@
+2014-10-16  Roger Fong  <roger_fong@apple.com>
+
+        Calling glReadPixels with BGRA format on an NVIDIA machine with an opaque context returns the wrong alpha values.
+        https://bugs.webkit.org/show_bug.cgi?id=137793.
+        <rdar://problem/15408133>
+
+        Reviewed by Dean Jackson.
+
+        This fixes conformance test context/context-attribute-preserve-drawing-buffer.html.
+
+        * platform/graphics/opengl/GraphicsContext3DOpenGL.cpp:
+        (WebCore::GraphicsContext3D::readPixelsAndConvertToBGRAIfNecessary):
+        On an NVIDIA machine, when the context has alpha turned off, call glReadPixels with RGBA format and then convert to RGBA.
+
 2014-10-17  Chris Dumez  <cdumez@apple.com>
 
         Use is<>() / downcast<>() for all SVG RenderObjects
index 56f9cec..8d87279 100644 (file)
 #include <wtf/MainThread.h>
 #include <wtf/text/CString.h>
 
+#if USE(ACCELERATE)
+#include <Accelerate/Accelerate.h>
+#endif
+
 #if PLATFORM(IOS)
 #import <OpenGLES/ES2/glext.h>
 // From <OpenGLES/glext.h>
@@ -65,7 +69,32 @@ void GraphicsContext3D::releaseShaderCompiler()
 
 void GraphicsContext3D::readPixelsAndConvertToBGRAIfNecessary(int x, int y, int width, int height, unsigned char* pixels)
 {
-    ::glReadPixels(x, y, width, height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, pixels);
+    // NVIDIA drivers have a bug where calling readPixels in BGRA can return the wrong values for the alpha channel when the alpha is off for the context.
+    if (!m_attrs.alpha && getExtensions()->isNVIDIA()) {
+        ::glReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
+#if USE(ACCELERATE)
+        vImage_Buffer src;
+        src.height = height;
+        src.width = width;
+        src.rowBytes = width*4;
+        src.data = pixels;
+
+        vImage_Buffer dest;
+        dest.height = height;
+        dest.width = width;
+        dest.rowBytes = width*4;
+        dest.data = pixels;
+
+        // Swap pixel channels from RGBA to BGRA.
+        const uint8_t map[4] = { 2, 1, 0, 3 };
+        vImagePermuteChannels_ARGB8888(&src, &dest, map, kvImageNoFlags);
+#else
+        int totalBytes = width * height * 4;
+        for (int i = 0; i < totalBytes; i += 4)
+            std::swap(pixels[i], pixels[i + 2]);
+#endif
+    } else
+        ::glReadPixels(x, y, width, height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, pixels);
 }
 
 void GraphicsContext3D::validateAttributes()