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/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