Title: [193748] trunk/Source/WebCore
Revision
193748
Author
y...@igalia.com
Date
2015-12-08 06:20:28 -0800 (Tue, 08 Dec 2015)

Log Message

[ThreadedCompositor] Add support for Cairo GL-backed ImageBuffer.
https://bugs.webkit.org/show_bug.cgi?id=151986

Reviewed by Žan Doberšek.

This patch adds a support for accelerated 2d canvas which uses cairo-gl as its
backend to the threaded compositor. Basically, it applies same way to support
WebGL for the threaded compositor.

Unfortunately, we cannot swap the buffer for the accelerated 2d canvas because
it should preserve the buffer of the previous frame when drawing new contents.
Because of that, the surface of the accelerated 2d canvas will be copied for
each frame.

* platform/graphics/cairo/ImageBufferCairo.cpp:
(WebCore::ImageBufferData::ImageBufferData):
(WebCore::ImageBufferData::createCompositorBuffer): Prepare a texture
surface to push the rendered result to the compositing thread.
(WebCore::ImageBufferData::swapBuffersIfNeeded): Copies the contents
of the canvas's surface to the compositing texture.
(WebCore::ImageBufferData::createCairoGLSurface): Moved to the inside
of ImageBufferData.

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (193747 => 193748)


--- trunk/Source/WebCore/ChangeLog	2015-12-08 11:18:12 UTC (rev 193747)
+++ trunk/Source/WebCore/ChangeLog	2015-12-08 14:20:28 UTC (rev 193748)
@@ -1,3 +1,28 @@
+2015-12-08  Gwang Yoon Hwang  <y...@igalia.com>
+
+        [ThreadedCompositor] Add support for Cairo GL-backed ImageBuffer.
+        https://bugs.webkit.org/show_bug.cgi?id=151986
+
+        Reviewed by Žan Doberšek.
+
+        This patch adds a support for accelerated 2d canvas which uses cairo-gl as its
+        backend to the threaded compositor. Basically, it applies same way to support
+        WebGL for the threaded compositor.
+
+        Unfortunately, we cannot swap the buffer for the accelerated 2d canvas because
+        it should preserve the buffer of the previous frame when drawing new contents.
+        Because of that, the surface of the accelerated 2d canvas will be copied for
+        each frame.
+
+        * platform/graphics/cairo/ImageBufferCairo.cpp:
+        (WebCore::ImageBufferData::ImageBufferData):
+        (WebCore::ImageBufferData::createCompositorBuffer): Prepare a texture
+        surface to push the rendered result to the compositing thread.
+        (WebCore::ImageBufferData::swapBuffersIfNeeded): Copies the contents
+        of the canvas's surface to the compositing texture.
+        (WebCore::ImageBufferData::createCairoGLSurface): Moved to the inside
+        of ImageBufferData.
+
 2015-12-08  Joanmarie Diggs  <jdi...@igalia.com>
 
         [GTK] 15 accessibility tests fail since r186692.

Modified: trunk/Source/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp (193747 => 193748)


--- trunk/Source/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp	2015-12-08 11:18:12 UTC (rev 193747)
+++ trunk/Source/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp	2015-12-08 14:20:28 UTC (rev 193748)
@@ -53,6 +53,7 @@
 #include "TextureMapperGL.h"
 #include <cairo-gl.h>
 #if USE(COORDINATED_GRAPHICS_THREADED)
+#include "TextureMapperPlatformLayerBuffer.h"
 #include "TextureMapperPlatformLayerProxy.h"
 #endif
 #endif
@@ -65,12 +66,58 @@
     : m_platformContext(0)
     , m_size(size)
 #if ENABLE(ACCELERATED_2D_CANVAS)
+#if USE(COORDINATED_GRAPHICS_THREADED)
+    , m_platformLayerProxy(adoptRef(new TextureMapperPlatformLayerProxy))
+    , m_compositorTexture(0)
+#endif
     , m_texture(0)
 #endif
 {
 }
 
 #if ENABLE(ACCELERATED_2D_CANVAS)
+#if USE(COORDINATED_GRAPHICS_THREADED)
+void ImageBufferData::createCompositorBuffer()
+{
+    GLContext::sharingContext()->makeContextCurrent();
+
+    glGenTextures(1, &m_compositorTexture);
+    glBindTexture(GL_TEXTURE_2D, m_compositorTexture);
+    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+    glTexImage2D(GL_TEXTURE_2D, 0 , GL_RGBA, m_size.width(), m_size.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
+
+    cairo_device_t* device = GLContext::sharingContext()->cairoDevice();
+    m_compositorSurface = adoptRef(cairo_gl_surface_create_for_texture(device, CAIRO_CONTENT_COLOR_ALPHA, m_compositorTexture, m_size.width(), m_size.height()));
+    m_compositorCr = adoptRef(cairo_create(m_compositorSurface.get()));
+    cairo_set_antialias(m_compositorCr.get(), CAIRO_ANTIALIAS_NONE);
+}
+
+void ImageBufferData::swapBuffersIfNeeded()
+{
+    GLContext* previousActiveContext = GLContext::getCurrent();
+
+    if (!m_compositorTexture) {
+        createCompositorBuffer();
+        LockHolder holder(m_platformLayerProxy->lock());
+        m_platformLayerProxy->pushNextBuffer(std::make_unique<TextureMapperPlatformLayerBuffer>(m_compositorTexture, m_size, TextureMapperGL::ShouldBlend));
+    }
+
+    // It would be great if we could just swap the buffers here as we do with webgl, but that breaks the cases
+    // where one frame uses the content already rendered in the previous frame. So we just copy the content
+    // into the compositor buffer.
+    cairo_set_source_surface(m_compositorCr.get(), m_surface.get(), 0, 0);
+    cairo_set_operator(m_compositorCr.get(), CAIRO_OPERATOR_SOURCE);
+    cairo_paint(m_compositorCr.get());
+
+    if (previousActiveContext)
+        previousActiveContext->makeContextCurrent();
+}
+#endif
+
 void clearSurface(cairo_surface_t* surface)
 {
     if (cairo_surface_status(surface) != CAIRO_STATUS_SUCCESS)
@@ -81,14 +128,14 @@
     cairo_paint(cr.get());
 }
 
-PassRefPtr<cairo_surface_t> createCairoGLSurface(const FloatSize& size, uint32_t& texture)
+void ImageBufferData::createCairoGLSurface()
 {
     GLContext::sharingContext()->makeContextCurrent();
 
     // We must generate the texture ourselves, because there is no Cairo API for extracting it
     // from a pre-existing surface.
-    glGenTextures(1, &texture);
-    glBindTexture(GL_TEXTURE_2D, texture);
+    glGenTextures(1, &m_texture);
+    glBindTexture(GL_TEXTURE_2D, m_texture);
     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
@@ -96,7 +143,7 @@
 
     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
 
-    glTexImage2D(GL_TEXTURE_2D, 0 /* level */, GL_RGBA8, size.width(), size.height(), 0 /* border */, GL_RGBA, GL_UNSIGNED_BYTE, 0);
+    glTexImage2D(GL_TEXTURE_2D, 0 /* level */, GL_RGBA, m_size.width(), m_size.height(), 0 /* border */, GL_RGBA, GL_UNSIGNED_BYTE, 0);
 
     GLContext* context = GLContext::sharingContext();
     cairo_device_t* device = context->cairoDevice();
@@ -104,9 +151,8 @@
     // Thread-awareness is a huge performance hit on non-Intel drivers.
     cairo_gl_device_set_thread_aware(device, FALSE);
 
-    auto surface = adoptRef(cairo_gl_surface_create_for_texture(device, CAIRO_CONTENT_COLOR_ALPHA, texture, size.width(), size.height()));
-    clearSurface(surface.get());
-    return surface;
+    m_surface = adoptRef(cairo_gl_surface_create_for_texture(device, CAIRO_CONTENT_COLOR_ALPHA, m_texture, m_size.width(), m_size.height()));
+    clearSurface(m_surface.get());
 }
 #endif
 
@@ -121,7 +167,7 @@
 
 #if ENABLE(ACCELERATED_2D_CANVAS)
     if (renderingMode == Accelerated) {
-        m_data.m_surface = createCairoGLSurface(size, m_data.m_texture);
+        m_data.createCairoGLSurface();
         if (!m_data.m_surface || cairo_surface_status(m_data.m_surface.get()) != CAIRO_STATUS_SUCCESS)
             renderingMode = Unaccelerated; // If allocation fails, fall back to non-accelerated path.
     }
@@ -411,14 +457,7 @@
 }
 #endif
 
-#if ENABLE(ACCELERATED_2D_CANVAS)
-#if USE(COORDINATED_GRAPHICS_THREADED)
-RefPtr<TextureMapperPlatformLayerProxy> ImageBufferData::proxy() const
-{
-    notImplemented();
-    return nullptr;
-}
-#else
+#if ENABLE(ACCELERATED_2D_CANVAS) && !USE(COORDINATED_GRAPHICS_THREADED)
 void ImageBufferData::paintToTextureMapper(TextureMapper* textureMapper, const FloatRect& targetRect, const TransformationMatrix& matrix, float opacity)
 {
     ASSERT(m_texture);
@@ -431,7 +470,6 @@
     static_cast<TextureMapperGL*>(textureMapper)->drawTexture(m_texture, TextureMapperGL::ShouldBlend, m_size, targetRect, matrix, opacity);
 }
 #endif
-#endif
 
 PlatformLayer* ImageBuffer::platformLayer() const
 {

Modified: trunk/Source/WebCore/platform/graphics/cairo/ImageBufferDataCairo.h (193747 => 193748)


--- trunk/Source/WebCore/platform/graphics/cairo/ImageBufferDataCairo.h	2015-12-08 11:18:12 UTC (rev 193747)
+++ trunk/Source/WebCore/platform/graphics/cairo/ImageBufferDataCairo.h	2015-12-08 14:20:28 UTC (rev 193748)
@@ -62,9 +62,17 @@
     IntSize m_size;
 
 #if ENABLE(ACCELERATED_2D_CANVAS)
+    void createCairoGLSurface();
+
 #if USE(COORDINATED_GRAPHICS_THREADED)
-    virtual RefPtr<TextureMapperPlatformLayerProxy> proxy() const override;
-    virtual void swapBuffersIfNeeded() override { };
+    virtual RefPtr<TextureMapperPlatformLayerProxy> proxy() const override { return m_platformLayerProxy.copyRef(); }
+    virtual void swapBuffersIfNeeded() override;
+    void createCompositorBuffer();
+
+    RefPtr<TextureMapperPlatformLayerProxy> m_platformLayerProxy;
+    RefPtr<cairo_surface_t> m_compositorSurface;
+    uint32_t m_compositorTexture;
+    RefPtr<cairo_t> m_compositorCr;
 #else
     virtual void paintToTextureMapper(TextureMapper*, const FloatRect& target, const TransformationMatrix&, float opacity);
 #endif
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to