Title: [104044] trunk/Source
Revision
104044
Author
[email protected]
Date
2012-01-04 09:17:09 -0800 (Wed, 04 Jan 2012)

Log Message

[chromium] Bypass the shadow texture copy for accelerated
canvas when running the compositor in single threaded mode.
https://bugs.webkit.org/show_bug.cgi?id=75146

Source/WebCore: 

The texture copy fails on Windows as glCopyTexImage2D() doesn't
support BGRA source textures.
This change also modifies Canvas2DLayerChromium::updateCompositorResources
to call glCopyTexSubImage2D() instead of glCopyTexImage2D() so that
the copy can work with texture allocated via the glTexStorage2D
extension.

Reviewed by James Robinson.

Tests: Canvas2DLayerChromiumTest.cpp

* platform/graphics/chromium/Canvas2DLayerChromium.cpp:
(WebCore::Canvas2DLayerChromium::Canvas2DLayerChromium):
(WebCore::Canvas2DLayerChromium::~Canvas2DLayerChromium):
(WebCore::Canvas2DLayerChromium::paintContentsIfDirty):
(WebCore::Canvas2DLayerChromium::setTextureManager):
(WebCore::Canvas2DLayerChromium::updateCompositorResources):
(WebCore::Canvas2DLayerChromium::pushPropertiesTo):
(WebCore::Canvas2DLayerChromium::unreserveContentsTexture):
(WebCore::Canvas2DLayerChromium::cleanupResources):
* platform/graphics/chromium/Canvas2DLayerChromium.h:

Source/WebKit/chromium: 

Modified Canvas2DLayerChromium unit test to test canvas with
both threaded and non-threaded compositing.

Reviewed by James Robinson.

* tests/CCSchedulerTestCommon.h:
(WebKitTests::FakeCCThread::threadID):
* tests/Canvas2DLayerChromiumTest.cpp:
(WebCore::Canvas2DLayerChromiumTest::setTextureManager):
(WebCore::Canvas2DLayerChromiumTest::fullLifecycleTest):
(WebCore::TEST_F):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (104043 => 104044)


--- trunk/Source/WebCore/ChangeLog	2012-01-04 17:08:14 UTC (rev 104043)
+++ trunk/Source/WebCore/ChangeLog	2012-01-04 17:17:09 UTC (rev 104044)
@@ -1,3 +1,31 @@
+2012-01-03  Vangelis Kokkevis  <[email protected]>
+
+        [chromium] Bypass the shadow texture copy for accelerated
+        canvas when running the compositor in single threaded mode.
+        https://bugs.webkit.org/show_bug.cgi?id=75146
+
+        The texture copy fails on Windows as glCopyTexImage2D() doesn't
+        support BGRA source textures.
+        This change also modifies Canvas2DLayerChromium::updateCompositorResources
+        to call glCopyTexSubImage2D() instead of glCopyTexImage2D() so that
+        the copy can work with texture allocated via the glTexStorage2D
+        extension.
+
+        Reviewed by James Robinson.
+
+        Tests: Canvas2DLayerChromiumTest.cpp
+
+        * platform/graphics/chromium/Canvas2DLayerChromium.cpp:
+        (WebCore::Canvas2DLayerChromium::Canvas2DLayerChromium):
+        (WebCore::Canvas2DLayerChromium::~Canvas2DLayerChromium):
+        (WebCore::Canvas2DLayerChromium::paintContentsIfDirty):
+        (WebCore::Canvas2DLayerChromium::setTextureManager):
+        (WebCore::Canvas2DLayerChromium::updateCompositorResources):
+        (WebCore::Canvas2DLayerChromium::pushPropertiesTo):
+        (WebCore::Canvas2DLayerChromium::unreserveContentsTexture):
+        (WebCore::Canvas2DLayerChromium::cleanupResources):
+        * platform/graphics/chromium/Canvas2DLayerChromium.h:
+
 2012-01-04  Adam Roben  <[email protected]>
 
         Use one big printf command instead of many chained echo commands to generate idl_files.tmp

Modified: trunk/Source/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.cpp (104043 => 104044)


--- trunk/Source/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.cpp	2012-01-04 17:08:14 UTC (rev 104043)
+++ trunk/Source/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.cpp	2012-01-04 17:17:09 UTC (rev 104044)
@@ -58,13 +58,16 @@
     , m_size(size)
     , m_backTextureId(0)
     , m_fbo(0)
+    , m_useDoubleBuffering(CCProxy::hasImplThread())
 {
-    GLC(m_context, m_fbo = m_context->createFramebuffer());
+    if (m_useDoubleBuffering)
+        GLC(m_context, m_fbo = m_context->createFramebuffer());
 }
 
 Canvas2DLayerChromium::~Canvas2DLayerChromium()
 {
-    GLC(m_context, m_context->deleteFramebuffer(m_fbo));
+    if (m_useDoubleBuffering && m_fbo)
+       GLC(m_context, m_context->deleteFramebuffer(m_fbo));
 }
 
 void Canvas2DLayerChromium::setTextureId(unsigned textureId)
@@ -92,7 +95,8 @@
     if (!drawsContent())
         return;
 
-    m_frontTexture->reserve(m_size, GraphicsContext3D::RGBA);
+    if (m_useDoubleBuffering)
+        m_frontTexture->reserve(m_size, GraphicsContext3D::RGBA);
 
     if (!needsDisplay())
         return;
@@ -121,7 +125,7 @@
 
 void Canvas2DLayerChromium::setTextureManager(TextureManager* textureManager)
 {
-    if (textureManager)
+    if (textureManager && m_useDoubleBuffering)
         m_frontTexture = ManagedTexture::create(textureManager);
     else
         m_frontTexture.clear();
@@ -129,14 +133,16 @@
 
 void Canvas2DLayerChromium::updateCompositorResources(GraphicsContext3D* context, CCTextureUpdater& updater)
 {
-    if (!m_backTextureId || !m_frontTexture->isValid(m_size, GraphicsContext3D::RGBA))
+    if (!m_backTextureId || !m_frontTexture || !m_frontTexture->isValid(m_size, GraphicsContext3D::RGBA))
         return;
 
     m_frontTexture->bindTexture(context, updater.allocator());
 
     GLC(context, context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_fbo));
     GLC(context, context->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::TEXTURE_2D, m_backTextureId, 0));
-    GLC(context, context->copyTexImage2D(GraphicsContext3D::TEXTURE_2D, 0, GraphicsContext3D::RGBA, 0, 0, m_size.width(), m_size.height(), 0));
+    // FIXME: The copy operation will fail if the m_backTexture is allocated as BGRA since glCopyTex(Sub)Image2D doesn't
+    //        support the BGRA format. See bug https://bugs.webkit.org/show_bug.cgi?id=75142
+    GLC(context, context->copyTexSubImage2D(GraphicsContext3D::TEXTURE_2D, 0, 0, 0, 0, 0, m_size.width(), m_size.height()));
     GLC(context, context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, 0));
     GLC(context, context->flush());
 }
@@ -146,17 +152,22 @@
     CanvasLayerChromium::pushPropertiesTo(layer);
 
     CCCanvasLayerImpl* canvasLayer = static_cast<CCCanvasLayerImpl*>(layer);
-    canvasLayer->setTextureId(m_frontTexture->textureId());
+    if (m_useDoubleBuffering)
+        canvasLayer->setTextureId(m_frontTexture->textureId());
+    else
+        canvasLayer->setTextureId(m_backTextureId);
 }
 
 void Canvas2DLayerChromium::unreserveContentsTexture()
 {
-    m_frontTexture->unreserve();
+    if (m_useDoubleBuffering)
+        m_frontTexture->unreserve();
 }
 
 void Canvas2DLayerChromium::cleanupResources()
 {
-    m_frontTexture.clear();
+    if (m_useDoubleBuffering)
+        m_frontTexture.clear();
 }
 
 }

Modified: trunk/Source/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.h (104043 => 104044)


--- trunk/Source/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.h	2012-01-04 17:08:14 UTC (rev 104043)
+++ trunk/Source/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.h	2012-01-04 17:17:09 UTC (rev 104044)
@@ -71,6 +71,10 @@
     IntSize m_size;
     unsigned m_backTextureId;
     Platform3DObject m_fbo;
+    // When m_useDoubleBuffering is true, the compositor will draw using a copy of the
+    // canvas' backing texture. This option should be used with the compositor doesn't
+    // synchronize its draws with the canvas updates.
+    bool m_useDoubleBuffering;
     OwnPtr<ManagedTexture> m_frontTexture;
 };
 

Modified: trunk/Source/WebKit/chromium/ChangeLog (104043 => 104044)


--- trunk/Source/WebKit/chromium/ChangeLog	2012-01-04 17:08:14 UTC (rev 104043)
+++ trunk/Source/WebKit/chromium/ChangeLog	2012-01-04 17:17:09 UTC (rev 104044)
@@ -1,3 +1,21 @@
+2012-01-03  Vangelis Kokkevis  <[email protected]>
+
+        [chromium] Bypass the shadow texture copy for accelerated
+        canvas when running the compositor in single threaded mode.
+        https://bugs.webkit.org/show_bug.cgi?id=75146
+
+        Modified Canvas2DLayerChromium unit test to test canvas with
+        both threaded and non-threaded compositing.
+
+        Reviewed by James Robinson.
+
+        * tests/CCSchedulerTestCommon.h:
+        (WebKitTests::FakeCCThread::threadID):
+        * tests/Canvas2DLayerChromiumTest.cpp:
+        (WebCore::Canvas2DLayerChromiumTest::setTextureManager):
+        (WebCore::Canvas2DLayerChromiumTest::fullLifecycleTest):
+        (WebCore::TEST_F):
+
 2012-01-04  Peter Beverloo  <[email protected]>
 
         [Chromium] Re-use TestShellLinux.cpp for Android

Modified: trunk/Source/WebKit/chromium/tests/CCSchedulerTestCommon.h (104043 => 104044)


--- trunk/Source/WebKit/chromium/tests/CCSchedulerTestCommon.h	2012-01-04 17:08:14 UTC (rev 104043)
+++ trunk/Source/WebKit/chromium/tests/CCSchedulerTestCommon.h	2012-01-04 17:17:09 UTC (rev 104044)
@@ -74,7 +74,7 @@
         m_pendingTask = task;
         m_pendingTaskDelay = delay;
     }
-    virtual WTF::ThreadIdentifier threadID() const { ASSERT_NOT_REACHED(); return 0; }
+    virtual WTF::ThreadIdentifier threadID() const { return 0; }
 
 protected:
     OwnPtr<Task> m_pendingTask;

Modified: trunk/Source/WebKit/chromium/tests/Canvas2DLayerChromiumTest.cpp (104043 => 104044)


--- trunk/Source/WebKit/chromium/tests/Canvas2DLayerChromiumTest.cpp	2012-01-04 17:08:14 UTC (rev 104043)
+++ trunk/Source/WebKit/chromium/tests/Canvas2DLayerChromiumTest.cpp	2012-01-04 17:17:09 UTC (rev 104044)
@@ -26,6 +26,7 @@
 
 #include "Canvas2DLayerChromium.h"
 
+#include "CCSchedulerTestCommon.h"
 #include "FakeWebGraphicsContext3D.h"
 #include "GraphicsContext3DPrivate.h"
 #include "TextureManager.h"
@@ -39,23 +40,11 @@
 
 using namespace WebCore;
 using namespace WebKit;
+using namespace WebKitTests;
 using testing::InSequence;
 using testing::Return;
 using testing::Test;
 
-namespace WebCore {
-
-class Canvas2DLayerChromiumTest : public Test {
-protected:
-    // This indirection is needed because individual tests aren't friends of Canvas2DLayerChromium.
-    void setTextureManager(Canvas2DLayerChromium* layer, TextureManager* manager)
-    {
-        layer->setTextureManager(manager);
-    }
-};
-
-}
-
 namespace {
 
 class MockCanvasContext : public FakeWebGraphicsContext3D {
@@ -67,7 +56,7 @@
     MOCK_METHOD5(framebufferTexture2D, void(WGC3Denum, WGC3Denum, WGC3Denum, WebGLId, WGC3Dint));
 
     MOCK_METHOD2(bindTexture, void(WGC3Denum, WebGLId));
-    MOCK_METHOD8(copyTexImage2D, void(WGC3Denum, WGC3Dint, WGC3Denum, WGC3Dint, WGC3Dint, WGC3Dsizei, WGC3Dsizei, WGC3Dint));
+    MOCK_METHOD8(copyTexSubImage2D, void(WGC3Denum, WGC3Dint, WGC3Dint, WGC3Dint, WGC3Dint, WGC3Dint, WGC3Dsizei, WGC3Dsizei));
 
     MOCK_METHOD1(deleteFramebuffer, void(WebGLId));
     MOCK_METHOD1(deleteTexture, void(WebGLId));
@@ -79,73 +68,106 @@
     MOCK_METHOD3(deleteTexture, void(unsigned, const IntSize&, GC3Denum));
 };
 
-TEST_F(Canvas2DLayerChromiumTest, testFullLifecycle)
-{
-    GraphicsContext3D::Attributes attrs;
+} // namespace
 
-    RefPtr<GraphicsContext3D> mainContext = GraphicsContext3DPrivate::createGraphicsContextFromWebContext(adoptPtr(new MockCanvasContext()), attrs, 0, GraphicsContext3D::RenderDirectlyToHostWindow, GraphicsContext3DPrivate::ForUseOnThisThread);
-    RefPtr<GraphicsContext3D> implContext = GraphicsContext3DPrivate::createGraphicsContextFromWebContext(adoptPtr(new MockCanvasContext()), attrs, 0, GraphicsContext3D::RenderDirectlyToHostWindow, GraphicsContext3DPrivate::ForUseOnThisThread);
+namespace WebCore {
 
-    MockCanvasContext& mainMock = *static_cast<MockCanvasContext*>(GraphicsContext3DPrivate::extractWebGraphicsContext3D(mainContext.get()));
-    MockCanvasContext& implMock = *static_cast<MockCanvasContext*>(GraphicsContext3DPrivate::extractWebGraphicsContext3D(implContext.get()));
+class Canvas2DLayerChromiumTest : public Test {
+protected:
+    // This indirection is needed because individual tests aren't friends of Canvas2DLayerChromium.
+    void setTextureManager(Canvas2DLayerChromium* layer, TextureManager* manager)
+    {
+        layer->setTextureManager(manager);
+    }
 
-    MockTextureAllocator allocatorMock;
-    CCTextureUpdater updater(&allocatorMock);
+    void fullLifecycleTest(bool threaded)
+    {
+        GraphicsContext3D::Attributes attrs;
 
-    const IntSize size(300, 150);
-    const size_t maxTextureSize = size.width() * size.height() * 4;
-    OwnPtr<TextureManager> textureManager = TextureManager::create(maxTextureSize, maxTextureSize, maxTextureSize);
+        RefPtr<GraphicsContext3D> mainContext = GraphicsContext3DPrivate::createGraphicsContextFromWebContext(adoptPtr(new MockCanvasContext()), attrs, 0, GraphicsContext3D::RenderDirectlyToHostWindow, GraphicsContext3DPrivate::ForUseOnThisThread);
+        RefPtr<GraphicsContext3D> implContext = GraphicsContext3DPrivate::createGraphicsContextFromWebContext(adoptPtr(new MockCanvasContext()), attrs, 0, GraphicsContext3D::RenderDirectlyToHostWindow, GraphicsContext3DPrivate::ForUseOnThisThread);
 
-    const WebGLId backTextureId = 1;
-    const WebGLId frontTextureId = 2;
-    const WebGLId fboId = 3;
-    {
-        InSequence sequence;
+        MockCanvasContext& mainMock = *static_cast<MockCanvasContext*>(GraphicsContext3DPrivate::extractWebGraphicsContext3D(mainContext.get()));
+        MockCanvasContext& implMock = *static_cast<MockCanvasContext*>(GraphicsContext3DPrivate::extractWebGraphicsContext3D(implContext.get()));
 
-        // Setup Canvas2DLayerChromium (on the main thread).
-        EXPECT_CALL(mainMock, createFramebuffer())
-            .WillOnce(Return(fboId));
+        MockTextureAllocator allocatorMock;
+        CCTextureUpdater updater(&allocatorMock);
 
-        // Create texture and do the copy (on the impl thread).
-        EXPECT_CALL(allocatorMock, createTexture(size, GraphicsContext3D::RGBA))
-            .WillOnce(Return(frontTextureId));
-        EXPECT_CALL(implMock, bindTexture(GraphicsContext3D::TEXTURE_2D, frontTextureId));
-        EXPECT_CALL(implMock, bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, fboId));
-        EXPECT_CALL(implMock, framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::TEXTURE_2D, backTextureId, 0));
-        EXPECT_CALL(implMock, copyTexImage2D(GraphicsContext3D::TEXTURE_2D, 0, GraphicsContext3D::RGBA, 0, 0, 300, 150, 0));
-        EXPECT_CALL(implMock, bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, 0));
+        const IntSize size(300, 150);
+        const size_t maxTextureSize = size.width() * size.height() * 4;
+        OwnPtr<TextureManager> textureManager = TextureManager::create(maxTextureSize, maxTextureSize, maxTextureSize);
 
-        // Teardown Canvas2DLayerChromium.
-        EXPECT_CALL(mainMock, deleteFramebuffer(fboId));
+        if (threaded)
+            CCProxy::setImplThread(new FakeCCThread);
 
-        // Teardown TextureManager.
-        EXPECT_CALL(allocatorMock, deleteTexture(frontTextureId, size, GraphicsContext3D::RGBA));
-    }
+        const WebGLId backTextureId = 1;
+        const WebGLId frontTextureId = 2;
+        const WebGLId fboId = 3;
+        {
+            InSequence sequence;
 
-    RefPtr<Canvas2DLayerChromium> canvas = Canvas2DLayerChromium::create(mainContext.get(), size);
-    canvas->setIsDrawable(true);
-    setTextureManager(canvas.get(), textureManager.get());
-    canvas->setBounds(IntSize(600, 300));
-    canvas->setTextureId(backTextureId);
+            // Note that the canvas backing texture is doublebuffered only when using the threaded
+            // compositor.
+            if (threaded) {
+                // Setup Canvas2DLayerChromium (on the main thread).
+                EXPECT_CALL(mainMock, createFramebuffer())
+                    .WillOnce(Return(fboId));
 
-    canvas->contentChanged();
-    EXPECT_TRUE(canvas->needsDisplay());
-    canvas->paintContentsIfDirty();
-    EXPECT_FALSE(canvas->needsDisplay());
-    {
-        DebugScopedSetImplThread scopedImplThread;
+                // Create texture and do the copy (on the impl thread).
+                EXPECT_CALL(allocatorMock, createTexture(size, GraphicsContext3D::RGBA))
+                    .WillOnce(Return(frontTextureId));
+                EXPECT_CALL(implMock, bindTexture(GraphicsContext3D::TEXTURE_2D, frontTextureId));
+                EXPECT_CALL(implMock, bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, fboId));
+                EXPECT_CALL(implMock, framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::TEXTURE_2D, backTextureId, 0));
+                EXPECT_CALL(implMock, copyTexSubImage2D(GraphicsContext3D::TEXTURE_2D, 0, 0, 0, 0, 0, 300, 150));
+                EXPECT_CALL(implMock, bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, 0));
 
-        RefPtr<CCLayerImpl> layerImpl = canvas->createCCLayerImpl();
-        EXPECT_EQ(0u, static_cast<CCCanvasLayerImpl*>(layerImpl.get())->textureId());
+                // Teardown Canvas2DLayerChromium.
+                EXPECT_CALL(mainMock, deleteFramebuffer(fboId));
 
-        canvas->updateCompositorResources(implContext.get(), updater);
-        canvas->pushPropertiesTo(layerImpl.get());
+                // Teardown TextureManager.
+                EXPECT_CALL(allocatorMock, deleteTexture(frontTextureId, size, GraphicsContext3D::RGBA));
+            }
+        }
 
-        EXPECT_EQ(frontTextureId, static_cast<CCCanvasLayerImpl*>(layerImpl.get())->textureId());
+        RefPtr<Canvas2DLayerChromium> canvas = Canvas2DLayerChromium::create(mainContext.get(), size);
+        canvas->setIsDrawable(true);
+        setTextureManager(canvas.get(), textureManager.get());
+        canvas->setBounds(IntSize(600, 300));
+        canvas->setTextureId(backTextureId);
+
+        canvas->contentChanged();
+        EXPECT_TRUE(canvas->needsDisplay());
+        canvas->paintContentsIfDirty();
+        EXPECT_FALSE(canvas->needsDisplay());
+        {
+            DebugScopedSetImplThread scopedImplThread;
+
+            RefPtr<CCLayerImpl> layerImpl = canvas->createCCLayerImpl();
+            EXPECT_EQ(0u, static_cast<CCCanvasLayerImpl*>(layerImpl.get())->textureId());
+
+            canvas->updateCompositorResources(implContext.get(), updater);
+            canvas->pushPropertiesTo(layerImpl.get());
+
+            if (threaded)
+                EXPECT_EQ(frontTextureId, static_cast<CCCanvasLayerImpl*>(layerImpl.get())->textureId());
+            else
+                EXPECT_EQ(backTextureId, static_cast<CCCanvasLayerImpl*>(layerImpl.get())->textureId());
+        }
+        canvas.clear();
+        textureManager->reduceMemoryToLimit(0);
+        textureManager->deleteEvictedTextures(&allocatorMock);
     }
-    canvas.clear();
-    textureManager->reduceMemoryToLimit(0);
-    textureManager->deleteEvictedTextures(&allocatorMock);
+};
+
+TEST_F(Canvas2DLayerChromiumTest, testFullLifecycleSingleThread)
+{
+    fullLifecycleTest(false);
 }
 
-} // namespace
+TEST_F(Canvas2DLayerChromiumTest, testFullLifecycleThreaded)
+{
+    fullLifecycleTest(true);
+}
+
+} // namespace webcore
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to