Title: [261639] trunk/Source/WebCore
Revision
261639
Author
[email protected]
Date
2020-05-13 12:57:05 -0700 (Wed, 13 May 2020)

Log Message

Bad flicker on three.js example
https://bugs.webkit.org/show_bug.cgi?id=183151

Patch by Kenneth Russell <[email protected]> on 2020-05-13
Reviewed by Dean Jackson.

With preserveDrawingBuffer:true and antialias:false, allocate an
intermediate texture and FBO, and blit from it to the destination
texture in prepareTexture(). Use wipeAlphaChannelFromPixels on iOS
as well as macOS.

In addition to fixing the test case from the bug, this also fixes
the webgl/2.0.0/conformance2/textures/webgl_canvas/ layout tests,
which will be re-enabled in a subsequent patch. It also passes the
more stringent webgl_canvas conformance tests in
https://github.com/KhronosGroup/WebGL/pull/3071 .

* platform/graphics/angle/GraphicsContextGLANGLE.cpp:
(WebCore::GraphicsContextGLOpenGL::readPixelsAndConvertToBGRAIfNecessary):
(WebCore::GraphicsContextGLOpenGL::reshapeFBOs):
(WebCore::GraphicsContextGLOpenGL::resolveMultisamplingIfNecessary):
(WebCore::GraphicsContextGLOpenGL::readPixels):
(WebCore::GraphicsContextGLOpenGL::validateDepthStencil):
(WebCore::GraphicsContextGLOpenGL::prepareTexture):
(WebCore::GraphicsContextGLOpenGL::reshape):
* platform/graphics/cocoa/GraphicsContextGLOpenGLCocoa.mm:
(WebCore::GraphicsContextGLOpenGL::GraphicsContextGLOpenGL):
(WebCore::GraphicsContextGLOpenGL::~GraphicsContextGLOpenGL):
* platform/graphics/opengl/GraphicsContextGLOpenGL.h:

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (261638 => 261639)


--- trunk/Source/WebCore/ChangeLog	2020-05-13 19:43:10 UTC (rev 261638)
+++ trunk/Source/WebCore/ChangeLog	2020-05-13 19:57:05 UTC (rev 261639)
@@ -1,3 +1,34 @@
+2020-05-13  Kenneth Russell  <[email protected]>
+
+        Bad flicker on three.js example
+        https://bugs.webkit.org/show_bug.cgi?id=183151
+
+        Reviewed by Dean Jackson.
+
+        With preserveDrawingBuffer:true and antialias:false, allocate an
+        intermediate texture and FBO, and blit from it to the destination
+        texture in prepareTexture(). Use wipeAlphaChannelFromPixels on iOS
+        as well as macOS.
+
+        In addition to fixing the test case from the bug, this also fixes
+        the webgl/2.0.0/conformance2/textures/webgl_canvas/ layout tests,
+        which will be re-enabled in a subsequent patch. It also passes the
+        more stringent webgl_canvas conformance tests in
+        https://github.com/KhronosGroup/WebGL/pull/3071 .
+
+        * platform/graphics/angle/GraphicsContextGLANGLE.cpp:
+        (WebCore::GraphicsContextGLOpenGL::readPixelsAndConvertToBGRAIfNecessary):
+        (WebCore::GraphicsContextGLOpenGL::reshapeFBOs):
+        (WebCore::GraphicsContextGLOpenGL::resolveMultisamplingIfNecessary):
+        (WebCore::GraphicsContextGLOpenGL::readPixels):
+        (WebCore::GraphicsContextGLOpenGL::validateDepthStencil):
+        (WebCore::GraphicsContextGLOpenGL::prepareTexture):
+        (WebCore::GraphicsContextGLOpenGL::reshape):
+        * platform/graphics/cocoa/GraphicsContextGLOpenGLCocoa.mm:
+        (WebCore::GraphicsContextGLOpenGL::GraphicsContextGLOpenGL):
+        (WebCore::GraphicsContextGLOpenGL::~GraphicsContextGLOpenGL):
+        * platform/graphics/opengl/GraphicsContextGLOpenGL.h:
+
 2020-05-13  Wenson Hsieh  <[email protected]>
 
         [iOS] "Copy" context menu action for attachment element does not work in Mail

Modified: trunk/Source/WebCore/platform/graphics/angle/GraphicsContextGLANGLE.cpp (261638 => 261639)


--- trunk/Source/WebCore/platform/graphics/angle/GraphicsContextGLANGLE.cpp	2020-05-13 19:43:10 UTC (rev 261638)
+++ trunk/Source/WebCore/platform/graphics/angle/GraphicsContextGLANGLE.cpp	2020-05-13 19:57:05 UTC (rev 261639)
@@ -73,6 +73,35 @@
 
 static const char* packedDepthStencilExtensionName = "GL_OES_packed_depth_stencil";
 
+namespace {
+
+class ScopedResetBufferBinding {
+    WTF_MAKE_NONCOPYABLE(ScopedResetBufferBinding);
+public:
+    ScopedResetBufferBinding(bool shouldDoWork, GLenum bindingPointQuery, GLenum bindingPoint)
+        : m_bindingPointQuery(bindingPointQuery)
+        , m_bindingPoint(bindingPoint)
+    {
+        if (shouldDoWork)
+            gl::GetIntegerv(m_bindingPointQuery, &m_bindingValue);
+        if (m_bindingValue)
+            gl::BindBuffer(m_bindingPoint, 0);
+    }
+
+    ~ScopedResetBufferBinding()
+    {
+        if (m_bindingValue)
+            gl::BindBuffer(m_bindingPoint, m_bindingValue);
+    }
+
+private:
+    GLint m_bindingPointQuery { 0 };
+    GLint m_bindingPoint { 0 };
+    GLint m_bindingValue { 0 };
+};
+
+} // namespace anonymous
+
 void GraphicsContextGLOpenGL::releaseShaderCompiler()
 {
     makeContextCurrent();
@@ -79,7 +108,7 @@
     notImplemented();
 }
 
-#if PLATFORM(MAC)
+#if PLATFORM(MAC) || PLATFORM(IOS_FAMILY)
 static void wipeAlphaChannelFromPixels(int width, int height, unsigned char* pixels)
 {
     // We can assume this doesn't overflow because the calling functions
@@ -116,7 +145,7 @@
         std::swap(pixels[i], pixels[i + 2]);
 #endif
 
-#if PLATFORM(MAC)
+#if PLATFORM(MAC) || PLATFORM(IOS_FAMILY)
     if (!contextAttributes().alpha)
         wipeAlphaChannelFromPixels(width, height, pixels);
 #endif
@@ -191,7 +220,23 @@
 #if PLATFORM(COCOA)
     allocateIOSurfaceBackingStore(IntSize(width, height));
     updateFramebufferTextureBackingStoreFromLayer();
-    gl::FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GraphicsContextGL::IOSurfaceTextureTarget, m_texture, 0);
+    if (m_preserveDrawingBufferTexture) {
+        // The context requires the use of an intermediate texture in order to implement
+        // preserveDrawingBuffer:true without antialiasing.
+        GLint texture2DBinding = 0;
+        gl::GetIntegerv(GL_TEXTURE_BINDING_2D, &texture2DBinding);
+        gl::BindTexture(GL_TEXTURE_2D, m_preserveDrawingBufferTexture);
+        // Note that any pixel unpack buffer was unbound earlier, in reshape().
+        gl::TexImage2D(GL_TEXTURE_2D, 0, colorFormat, width, height, 0, colorFormat, GL_UNSIGNED_BYTE, 0);
+        // m_fbo is bound at this point.
+        gl::FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_preserveDrawingBufferTexture, 0);
+        gl::BindTexture(GL_TEXTURE_2D, texture2DBinding);
+        // Attach m_texture to m_preserveDrawingBufferFBO for later blitting.
+        gl::BindFramebuffer(GL_FRAMEBUFFER, m_preserveDrawingBufferFBO);
+        gl::FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GraphicsContextGL::IOSurfaceTextureTarget, m_texture, 0);
+        gl::BindFramebuffer(GL_FRAMEBUFFER, m_fbo);
+    } else
+        gl::FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GraphicsContextGL::IOSurfaceTextureTarget, m_texture, 0);
 #elif PLATFORM(GTK)
     gl::BindTexture(GL_TEXTURE_RECTANGLE_ANGLE, m_texture);
     gl::TexImage2D(GL_TEXTURE_RECTANGLE_ANGLE, 0, m_internalColorFormat, width, height, 0, colorFormat, GL_UNSIGNED_BYTE, 0);
@@ -254,8 +299,13 @@
     TemporaryANGLESetting scopedScissor(GL_SCISSOR_TEST, GL_FALSE);
     TemporaryANGLESetting scopedDither(GL_DITHER, GL_FALSE);
 
-    GLint boundFrameBuffer;
-    gl::GetIntegerv(GL_FRAMEBUFFER_BINDING, &boundFrameBuffer);
+    GLint boundFrameBuffer = 0;
+    GLint boundReadFrameBuffer = 0;
+    if (m_isForWebGL2) {
+        gl::GetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundFrameBuffer);
+        gl::GetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &boundReadFrameBuffer);
+    } else
+        gl::GetIntegerv(GL_FRAMEBUFFER_BINDING, &boundFrameBuffer);
     gl::BindFramebuffer(GL_READ_FRAMEBUFFER_ANGLE, m_multisampleFBO);
     gl::BindFramebuffer(GL_DRAW_FRAMEBUFFER_ANGLE, m_fbo);
 
@@ -267,7 +317,11 @@
         resolveRect = IntRect(0, 0, m_currentWidth, m_currentHeight);
 
     gl::BlitFramebufferANGLE(resolveRect.x(), resolveRect.y(), resolveRect.maxX(), resolveRect.maxY(), resolveRect.x(), resolveRect.y(), resolveRect.maxX(), resolveRect.maxY(), GL_COLOR_BUFFER_BIT, GL_NEAREST);
-    gl::BindFramebuffer(GL_FRAMEBUFFER, boundFrameBuffer);
+    if (m_isForWebGL2) {
+        gl::BindFramebuffer(GL_DRAW_FRAMEBUFFER, boundFrameBuffer);
+        gl::BindFramebuffer(GL_READ_FRAMEBUFFER, boundReadFrameBuffer);
+    } else
+        gl::BindFramebuffer(GL_FRAMEBUFFER, boundFrameBuffer);
 }
 
 void GraphicsContextGLOpenGL::renderbufferStorage(GCGLenum target, GCGLenum internalformat, GCGLsizei width, GCGLsizei height)
@@ -362,7 +416,7 @@
     if (attrs.antialias && m_state.boundReadFBO == m_multisampleFBO)
         gl::BindFramebuffer(framebufferTarget, m_multisampleFBO);
 
-#if PLATFORM(MAC)
+#if PLATFORM(MAC) || PLATFORM(IOS_FAMILY)
     if (!attrs.alpha && (format == GraphicsContextGL::RGBA || format == GraphicsContextGL::BGRA) && (m_state.boundReadFBO == m_fbo || (attrs.antialias && m_state.boundReadFBO == m_multisampleFBO)))
         wipeAlphaChannelFromPixels(width, height, static_cast<unsigned char*>(data));
 #endif
@@ -395,6 +449,9 @@
             extensions.ensureEnabled("GL_ANGLE_framebuffer_blit");
             extensions.ensureEnabled("GL_OES_rgb8_rgba8");
         }
+    } else if (attrs.preserveDrawingBuffer) {
+        // Needed for preserveDrawingBuffer:true support without antialiasing.
+        extensions.ensureEnabled("GL_ANGLE_framebuffer_blit");
     }
 }
 
@@ -483,6 +540,25 @@
     else
         gl::BindFramebuffer(GraphicsContextGL::FRAMEBUFFER, m_fbo);
 #else
+    if (m_preserveDrawingBufferTexture) {
+        // Blit m_preserveDrawingBufferTexture into m_texture.
+        gl::BindFramebuffer(GL_DRAW_FRAMEBUFFER_ANGLE, m_preserveDrawingBufferFBO);
+        gl::BindFramebuffer(GL_READ_FRAMEBUFFER_ANGLE, m_fbo);
+        gl::BlitFramebufferANGLE(0, 0, m_currentWidth, m_currentHeight, 0, 0, m_currentWidth, m_currentHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST);
+
+        // Note: it's been observed that BlitFramebuffer may destroy the alpha channel of the
+        // destination texture if it's an RGB texture bound to an IOSurface. This wasn't observable
+        // through the WebGL conformance tests, but it may be necessary to save and restore the
+        // color mask and clear color, and use the color mask to clear the alpha channel of the
+        // destination texture to 1.0.
+
+        // Restore user's framebuffer bindings.
+        if (m_isForWebGL2) {
+            gl::BindFramebuffer(GL_DRAW_FRAMEBUFFER, m_state.boundDrawFBO);
+            gl::BindFramebuffer(GL_READ_FRAMEBUFFER, m_state.boundReadFBO);
+        } else
+            gl::BindFramebuffer(GL_FRAMEBUFFER, m_state.boundDrawFBO);
+    }
     gl::Flush();
 #endif
 }
@@ -547,6 +623,7 @@
 
     TemporaryANGLESetting scopedScissor(GL_SCISSOR_TEST, GL_FALSE);
     TemporaryANGLESetting scopedDither(GL_DITHER, GL_FALSE);
+    ScopedResetBufferBinding scopedPixelUnpackBufferReset(m_isForWebGL2, GL_PIXEL_UNPACK_BUFFER_BINDING, GL_PIXEL_UNPACK_BUFFER);
 
     bool mustRestoreFBO = reshapeFBOs(IntSize(width, height));
     auto attrs = contextAttributes();

Modified: trunk/Source/WebCore/platform/graphics/cocoa/GraphicsContextGLOpenGLCocoa.mm (261638 => 261639)


--- trunk/Source/WebCore/platform/graphics/cocoa/GraphicsContextGLOpenGLCocoa.mm	2020-05-13 19:43:10 UTC (rev 261638)
+++ trunk/Source/WebCore/platform/graphics/cocoa/GraphicsContextGLOpenGLCocoa.mm	2020-05-13 19:57:05 UTC (rev 261639)
@@ -495,8 +495,19 @@
         gl::GenRenderbuffers(1, &m_multisampleColorBuffer);
         if (attrs.stencil || attrs.depth)
             gl::GenRenderbuffers(1, &m_multisampleDepthStencilBuffer);
+    } else if (attrs.preserveDrawingBuffer) {
+        // If necessary, create another texture to handle preserveDrawingBuffer:true without
+        // antialiasing.
+        gl::GenTextures(1, &m_preserveDrawingBufferTexture);
+        gl::BindTexture(GL_TEXTURE_2D, m_preserveDrawingBufferTexture);
+        gl::TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+        gl::TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+        gl::TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+        gl::TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+        gl::BindTexture(GL_TEXTURE_2D, 0);
+        // Create an FBO with which to perform BlitFramebuffer from one texture to the other.
+        gl::GenFramebuffers(1, &m_preserveDrawingBufferFBO);
     }
-
 #endif // USE(ANGLE)
 
 #if !USE(ANGLE)
@@ -580,6 +591,10 @@
                 gl::DeleteRenderbuffers(1, &m_depthStencilBuffer);
         }
         gl::DeleteFramebuffers(1, &m_fbo);
+        if (m_preserveDrawingBufferTexture)
+            gl::DeleteTextures(1, &m_preserveDrawingBufferTexture);
+        if (m_preserveDrawingBufferFBO)
+            gl::DeleteFramebuffers(1, &m_preserveDrawingBufferFBO);
 #endif
 
 #if USE(OPENGL_ES)

Modified: trunk/Source/WebCore/platform/graphics/opengl/GraphicsContextGLOpenGL.h (261638 => 261639)


--- trunk/Source/WebCore/platform/graphics/opengl/GraphicsContextGLOpenGL.h	2020-05-13 19:43:10 UTC (rev 261638)
+++ trunk/Source/WebCore/platform/graphics/opengl/GraphicsContextGLOpenGL.h	2020-05-13 19:57:05 UTC (rev 261639)
@@ -867,6 +867,13 @@
     GCGLuint m_multisampleDepthStencilBuffer { 0 };
     GCGLuint m_multisampleColorBuffer { 0 };
 
+#if USE(ANGLE)
+    // For preserveDrawingBuffer:true without multisampling.
+    GCGLuint m_preserveDrawingBufferTexture { 0 };
+    // Attaches m_texture when m_preserveDrawingBufferTexture is non-zero.
+    GCGLuint m_preserveDrawingBufferFBO { 0 };
+#endif
+
     // Errors raised by synthesizeGLError().
     ListHashSet<GCGLenum> m_syntheticErrors;
 
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to