diff options
26 files changed, 1406 insertions, 925 deletions
diff --git a/cc/cc_tests.gyp b/cc/cc_tests.gyp index 77647105..c9d944d 100644 --- a/cc/cc_tests.gyp +++ b/cc/cc_tests.gyp @@ -29,6 +29,7 @@ 'layer_tree_host_impl_unittest.cc', 'layer_tree_host_unittest.cc', 'layer_tree_host_unittest_animation.cc', + 'layer_tree_host_unittest_context.cc', 'layer_tree_host_unittest_occlusion.cc', 'layer_tree_host_unittest_scroll.cc', 'layer_unittest.cc', @@ -70,6 +71,8 @@ 'test/fake_content_layer.h', 'test/fake_content_layer_client.cc', 'test/fake_content_layer_client.h', + 'test/fake_content_layer_impl.cc', + 'test/fake_content_layer_impl.h', 'test/fake_impl_proxy.h', 'test/fake_output_surface.h', 'test/fake_layer_tree_host_client.cc', @@ -91,6 +94,10 @@ 'test/fake_output_surface.h', 'test/fake_software_output_device.cc', 'test/fake_software_output_device.h', + 'test/fake_video_frame.cc', + 'test/fake_video_frame.h', + 'test/fake_video_frame_provider.cc', + 'test/fake_video_frame_provider.h', 'test/fake_web_graphics_context_3d.cc', 'test/fake_web_graphics_context_3d.h', 'test/fake_web_scrollbar.cc', diff --git a/cc/heads_up_display_layer.h b/cc/heads_up_display_layer.h index 15061c6..2c97a86 100644 --- a/cc/heads_up_display_layer.h +++ b/cc/heads_up_display_layer.h @@ -6,12 +6,13 @@ #define CC_HEADS_UP_DISPLAY_LAYER_H_ #include "base/memory/scoped_ptr.h" +#include "cc/cc_export.h" #include "cc/font_atlas.h" #include "cc/layer.h" namespace cc { -class HeadsUpDisplayLayer : public Layer { +class CC_EXPORT HeadsUpDisplayLayer : public Layer { public: static scoped_refptr<HeadsUpDisplayLayer> create(); diff --git a/cc/layer_tree_host_impl_unittest.cc b/cc/layer_tree_host_impl_unittest.cc index af6082d..fea6e22 100644 --- a/cc/layer_tree_host_impl_unittest.cc +++ b/cc/layer_tree_host_impl_unittest.cc @@ -27,6 +27,8 @@ #include "cc/test/animation_test_common.h" #include "cc/test/fake_output_surface.h" #include "cc/test/fake_proxy.h" +#include "cc/test/fake_video_frame.h" +#include "cc/test/fake_video_frame_provider.h" #include "cc/test/fake_web_graphics_context_3d.h" #include "cc/test/fake_web_scrollbar_theme_geometry.h" #include "cc/test/geometry_test_utils.h" @@ -38,15 +40,11 @@ #include "cc/tiled_layer_impl.h" #include "cc/video_layer_impl.h" #include "media/base/media.h" -#include "media/base/video_frame.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" -#include "third_party/WebKit/Source/Platform/chromium/public/WebVideoFrame.h" -#include "third_party/WebKit/Source/Platform/chromium/public/WebVideoFrameProvider.h" #include "ui/gfx/size_conversions.h" #include "ui/gfx/vector2d_conversions.h" -using media::VideoFrame; using ::testing::Mock; using ::testing::Return; using ::testing::AnyNumber; @@ -2225,8 +2223,7 @@ public: .WillOnce(Return()) .RetiresOnSaturation(); - // 1 is hardcoded return value of fake createProgram() - EXPECT_CALL(*m_context, useProgram(1)) + EXPECT_CALL(*m_context, useProgram(_)) .WillOnce(Return()) .RetiresOnSaturation(); @@ -2454,509 +2451,6 @@ TEST_P(LayerTreeHostImplTest, contributingLayerEmptyScissorNoPartialSwap) } } -// Make sure that output surface lost notifications are propagated through the tree. -class OutputSurfaceLostNotificationCheckLayer : public LayerImpl { -public: - static scoped_ptr<LayerImpl> create(LayerTreeImpl* treeImpl, int id) { return scoped_ptr<LayerImpl>(new OutputSurfaceLostNotificationCheckLayer(treeImpl, id)); } - - virtual void didLoseOutputSurface() OVERRIDE - { - m_didLoseOutputSurfaceCalled = true; - } - - bool didLoseOutputSurfaceCalled() const { return m_didLoseOutputSurfaceCalled; } - -private: - OutputSurfaceLostNotificationCheckLayer(LayerTreeImpl* treeImpl, int id) - : LayerImpl(treeImpl, id) - , m_didLoseOutputSurfaceCalled(false) - { - } - - bool m_didLoseOutputSurfaceCalled; -}; - -TEST_P(LayerTreeHostImplTest, outputSurfaceLostAndRestoredNotificationSentToAllLayers) -{ - m_hostImpl->setRootLayer(OutputSurfaceLostNotificationCheckLayer::create(m_hostImpl->activeTree(), 1)); - OutputSurfaceLostNotificationCheckLayer* root = static_cast<OutputSurfaceLostNotificationCheckLayer*>(m_hostImpl->rootLayer()); - - root->addChild(OutputSurfaceLostNotificationCheckLayer::create(m_hostImpl->activeTree(), 2)); - OutputSurfaceLostNotificationCheckLayer* layer1 = static_cast<OutputSurfaceLostNotificationCheckLayer*>(root->children()[0]); - - layer1->addChild(OutputSurfaceLostNotificationCheckLayer::create(m_hostImpl->activeTree(), 3)); - OutputSurfaceLostNotificationCheckLayer* layer2 = static_cast<OutputSurfaceLostNotificationCheckLayer*>(layer1->children()[0]); - - EXPECT_FALSE(root->didLoseOutputSurfaceCalled()); - EXPECT_FALSE(layer1->didLoseOutputSurfaceCalled()); - EXPECT_FALSE(layer2->didLoseOutputSurfaceCalled()); - - m_hostImpl->initializeRenderer(createOutputSurface()); - - EXPECT_TRUE(root->didLoseOutputSurfaceCalled()); - EXPECT_TRUE(layer1->didLoseOutputSurfaceCalled()); - EXPECT_TRUE(layer2->didLoseOutputSurfaceCalled()); -} - -TEST_P(LayerTreeHostImplTest, finishAllRenderingAfterContextLost) -{ - LayerTreeSettings settings; - m_hostImpl = LayerTreeHostImpl::create(settings, this, &m_proxy); - - // The context initialization will fail, but we should still be able to call finishAllRendering() without any ill effects. - m_hostImpl->initializeRenderer(FakeOutputSurface::Create3d(scoped_ptr<WebKit::WebGraphicsContext3D>(new FakeWebGraphicsContext3DMakeCurrentFails)).PassAs<OutputSurface>()); - m_hostImpl->finishAllRendering(); -} - -class FakeWebGraphicsContext3DMakeCurrentFailsEventually : public FakeWebGraphicsContext3D { -public: - explicit FakeWebGraphicsContext3DMakeCurrentFailsEventually(unsigned succeedCount) : m_succeedCount(succeedCount) { } - virtual bool makeContextCurrent() { - if (!m_succeedCount) - return false; - --m_succeedCount; - return true; - } - -private: - unsigned m_succeedCount; -}; - -TEST_P(LayerTreeHostImplTest, context3DLostDuringInitialize) -{ - LayerTreeSettings settings; - m_hostImpl = LayerTreeHostImpl::create(settings, this, &m_proxy); - - // Initialize into a known successful state. - EXPECT_TRUE(m_hostImpl->initializeRenderer(createOutputSurface())); - EXPECT_TRUE(m_hostImpl->outputSurface()); - EXPECT_TRUE(m_hostImpl->renderer()); - EXPECT_TRUE(m_hostImpl->resourceProvider()); - - // We will make the context get lost after a numer of makeContextCurrent - // calls. The exact number of calls to make it succeed is dependent on the - // implementation and doesn't really matter (i.e. can be changed to make the - // tests pass after some refactoring). - const unsigned kMakeCurrentSuccessesNeededForSuccessfulInitialization = 3; - - for (unsigned i = 0; i < kMakeCurrentSuccessesNeededForSuccessfulInitialization; ++i) { - // The context will get lost during initialization, we shouldn't crash. We - // should also be in a consistent state. - EXPECT_FALSE(m_hostImpl->initializeRenderer(FakeOutputSurface::Create3d(scoped_ptr<WebKit::WebGraphicsContext3D>(new FakeWebGraphicsContext3DMakeCurrentFailsEventually(i))).PassAs<OutputSurface>())); - EXPECT_EQ(0, m_hostImpl->outputSurface()); - EXPECT_EQ(0, m_hostImpl->renderer()); - EXPECT_EQ(0, m_hostImpl->resourceProvider()); - EXPECT_TRUE(m_hostImpl->initializeRenderer(createOutputSurface())); - } - - EXPECT_TRUE(m_hostImpl->initializeRenderer(FakeOutputSurface::Create3d(scoped_ptr<WebKit::WebGraphicsContext3D>(new FakeWebGraphicsContext3DMakeCurrentFailsEventually(kMakeCurrentSuccessesNeededForSuccessfulInitialization))).PassAs<OutputSurface>())); - EXPECT_TRUE(m_hostImpl->outputSurface()); - EXPECT_TRUE(m_hostImpl->renderer()); - EXPECT_TRUE(m_hostImpl->resourceProvider()); -} - -// Fake WebKit::WebGraphicsContext3D that will cause a failure if trying to use a -// resource that wasn't created by it (resources created by -// FakeWebGraphicsContext3D have an id of 1). -class StrictWebGraphicsContext3D : public FakeWebGraphicsContext3D { -public: - StrictWebGraphicsContext3D() - : FakeWebGraphicsContext3D() - { - next_texture_id_ = 8; // Start allocating texture ids larger than any other resource IDs so we can tell if someone's mixing up their resource types. - } - - virtual WebKit::WebGLId createBuffer() { return 2; } - virtual WebKit::WebGLId createFramebuffer() { return 3; } - virtual WebKit::WebGLId createProgram() { return 4; } - virtual WebKit::WebGLId createRenderbuffer() { return 5; } - virtual WebKit::WebGLId createShader(WebKit::WGC3Denum) { return 6; } - - static const WebKit::WebGLId kExternalTextureId = 7; - - virtual void deleteBuffer(WebKit::WebGLId id) - { - if (id != 2) - ADD_FAILURE() << "Trying to delete buffer id " << id; - } - - virtual void deleteFramebuffer(WebKit::WebGLId id) - { - if (id != 3) - ADD_FAILURE() << "Trying to delete framebuffer id " << id; - } - - virtual void deleteProgram(WebKit::WebGLId id) - { - if (id != 4) - ADD_FAILURE() << "Trying to delete program id " << id; - } - - virtual void deleteRenderbuffer(WebKit::WebGLId id) - { - if (id != 5) - ADD_FAILURE() << "Trying to delete renderbuffer id " << id; - } - - virtual void deleteShader(WebKit::WebGLId id) - { - if (id != 6) - ADD_FAILURE() << "Trying to delete shader id " << id; - } - - virtual WebKit::WebGLId createTexture() - { - unsigned textureId = FakeWebGraphicsContext3D::createTexture(); - m_allocatedTextureIds.insert(textureId); - return textureId; - } - virtual void deleteTexture(WebKit::WebGLId id) - { - if (id == kExternalTextureId) - ADD_FAILURE() << "Trying to delete external texture"; - if (!ContainsKey(m_allocatedTextureIds, id)) - ADD_FAILURE() << "Trying to delete texture id " << id; - m_allocatedTextureIds.erase(id); - } - - virtual void bindBuffer(WebKit::WGC3Denum, WebKit::WebGLId id) - { - if (id != 2 && id) - ADD_FAILURE() << "Trying to bind buffer id " << id; - } - - virtual void bindFramebuffer(WebKit::WGC3Denum, WebKit::WebGLId id) - { - if (id != 3 && id) - ADD_FAILURE() << "Trying to bind framebuffer id " << id; - } - - virtual void useProgram(WebKit::WebGLId id) - { - if (id != 4) - ADD_FAILURE() << "Trying to use program id " << id; - } - - virtual void bindRenderbuffer(WebKit::WGC3Denum, WebKit::WebGLId id) - { - if (id != 5 && id) - ADD_FAILURE() << "Trying to bind renderbuffer id " << id; - } - - virtual void attachShader(WebKit::WebGLId program, WebKit::WebGLId shader) - { - if ((program != 4) || (shader != 6)) - ADD_FAILURE() << "Trying to attach shader id " << shader << " to program id " << program; - } - - virtual void bindTexture(WebKit::WGC3Denum, WebKit::WebGLId id) - { - if (id && id != kExternalTextureId && !ContainsKey(m_allocatedTextureIds, id)) - ADD_FAILURE() << "Trying to bind texture id " << id; - } - -private: - base::hash_set<unsigned> m_allocatedTextureIds; -}; - -// Fake WebKit::WebVideoFrame wrapper of media::VideoFrame. -class FakeVideoFrame: public WebKit::WebVideoFrame { -public: - explicit FakeVideoFrame(const scoped_refptr<VideoFrame>& frame) : m_frame(frame) { } - virtual ~FakeVideoFrame() { } - - virtual Format format() const { NOTREACHED(); return FormatInvalid; } - virtual unsigned width() const { NOTREACHED(); return 0; } - virtual unsigned height() const { NOTREACHED(); return 0; } - virtual unsigned planes() const { NOTREACHED(); return 0; } - virtual int stride(unsigned plane) const { NOTREACHED(); return 0; } - virtual const void* data(unsigned plane) const { NOTREACHED(); return NULL; } - virtual unsigned textureId() const { NOTREACHED(); return 0; } - virtual unsigned textureTarget() const { NOTREACHED(); return 0; } - virtual WebKit::WebRect visibleRect() const { NOTREACHED(); return WebKit::WebRect(0, 0, 0, 0); } - virtual WebKit::WebSize textureSize() const { NOTREACHED(); return WebKit::WebSize(4, 4); } - - static VideoFrame* toVideoFrame(WebKit::WebVideoFrame* web_video_frame) { - FakeVideoFrame* wrapped_frame = - static_cast<FakeVideoFrame*>(web_video_frame); - if (wrapped_frame) - return wrapped_frame->m_frame.get(); - return NULL; - } - -private: - scoped_refptr<VideoFrame> m_frame; -}; - -// Fake video frame provider that always provides the same FakeVideoFrame. -class FakeVideoFrameProvider: public WebKit::WebVideoFrameProvider { -public: - FakeVideoFrameProvider() : m_frame(0), m_client(0) { } - virtual ~FakeVideoFrameProvider() - { - if (m_client) - m_client->stopUsingProvider(); - } - - virtual void setVideoFrameProviderClient(Client* client) { m_client = client; } - virtual WebKit::WebVideoFrame* getCurrentFrame() { return m_frame; } - virtual void putCurrentFrame(WebKit::WebVideoFrame*) { } - - void setFrame(WebKit::WebVideoFrame* frame) { m_frame = frame; } - -private: - WebKit::WebVideoFrame* m_frame; - Client* m_client; -}; - -class StrictWebGraphicsContext3DWithIOSurface : public StrictWebGraphicsContext3D { -public: - virtual WebKit::WebString getString(WebKit::WGC3Denum name) OVERRIDE - { - if (name == GL_EXTENSIONS) - return WebKit::WebString("GL_CHROMIUM_iosurface GL_ARB_texture_rectangle"); - - return WebKit::WebString(); - } -}; - -class FakeWebGraphicsContext3DWithIOSurface : public FakeWebGraphicsContext3D { -public: - virtual WebKit::WebString getString(WebKit::WGC3Denum name) OVERRIDE - { - if (name == GL_EXTENSIONS) - return WebKit::WebString("GL_CHROMIUM_iosurface GL_ARB_texture_rectangle"); - - return WebKit::WebString(); - } -}; - -class FakeWebScrollbarThemeGeometryNonEmpty : public FakeWebScrollbarThemeGeometry { - virtual WebKit::WebRect trackRect(WebKit::WebScrollbar*) OVERRIDE { return WebKit::WebRect(0, 0, 10, 10); } - virtual WebKit::WebRect thumbRect(WebKit::WebScrollbar*) OVERRIDE { return WebKit::WebRect(0, 5, 5, 2); } - virtual void splitTrack(WebKit::WebScrollbar*, const WebKit::WebRect& track, WebKit::WebRect& startTrack, WebKit::WebRect& thumb, WebKit::WebRect& endTrack) OVERRIDE - { - thumb = WebKit::WebRect(0, 5, 5, 2); - startTrack = WebKit::WebRect(0, 5, 0, 5); - endTrack = WebKit::WebRect(0, 0, 0, 5); - } -}; - -class FakeScrollbarLayerImpl : public ScrollbarLayerImpl { -public: - static scoped_ptr<FakeScrollbarLayerImpl> create(LayerTreeImpl* treeImpl, int id) - { - return make_scoped_ptr(new FakeScrollbarLayerImpl(treeImpl, id)); - } - - void createResources(ResourceProvider* provider) - { - DCHECK(provider); - gfx::Size size(10, 10); - GLenum format = GL_RGBA; - ResourceProvider::TextureUsageHint hint = ResourceProvider::TextureUsageAny; - setScrollbarGeometry(ScrollbarGeometryFixedThumb::create(FakeWebScrollbarThemeGeometryNonEmpty::create())); - - setBackTrackResourceId(provider->createResource(size, format, hint)); - setForeTrackResourceId(provider->createResource(size, format, hint)); - setThumbResourceId(provider->createResource(size, format, hint)); - } - -protected: - FakeScrollbarLayerImpl(LayerTreeImpl* treeImpl, int id) - : ScrollbarLayerImpl(treeImpl, id) - { - } -}; - -static inline scoped_ptr<RenderPass> createRenderPassWithResource(ResourceProvider* provider) -{ - ResourceProvider::ResourceId resourceId = provider->createResource(gfx::Size(1, 1), GL_RGBA, ResourceProvider::TextureUsageAny); - - scoped_ptr<TestRenderPass> pass = TestRenderPass::Create(); - pass->SetNew(RenderPass::Id(1, 1), gfx::Rect(0, 0, 1, 1), gfx::Rect(0, 0, 1, 1), gfx::Transform()); - scoped_ptr<SharedQuadState> sharedState = SharedQuadState::Create(); - sharedState->SetAll(gfx::Transform(), gfx::Rect(0, 0, 1, 1), gfx::Rect(0, 0, 1, 1), gfx::Rect(0, 0, 1, 1), false, 1); - const float vertex_opacity[] = {1.0f, 1.0f, 1.0f, 1.0f}; - scoped_ptr<TextureDrawQuad> quad = TextureDrawQuad::Create(); - quad->SetNew(sharedState.get(), gfx::Rect(0, 0, 1, 1), gfx::Rect(0, 0, 1, 1), resourceId, false, gfx::RectF(0, 0, 1, 1), vertex_opacity, false); - - pass->AppendSharedQuadState(sharedState.Pass()); - pass->AppendQuad(quad.PassAs<DrawQuad>()); - - return pass.PassAs<RenderPass>(); -} - -TEST_P(LayerTreeHostImplTest, dontUseOldResourcesAfterLostOutputSurface) -{ - int layerId = 1; - - scoped_ptr<LayerImpl> rootLayer(LayerImpl::create(m_hostImpl->activeTree(), layerId++)); - rootLayer->setBounds(gfx::Size(10, 10)); - rootLayer->setAnchorPoint(gfx::PointF(0, 0)); - - scoped_ptr<TiledLayerImpl> tileLayer = TiledLayerImpl::create(m_hostImpl->activeTree(), layerId++); - tileLayer->setBounds(gfx::Size(10, 10)); - tileLayer->setAnchorPoint(gfx::PointF(0, 0)); - tileLayer->setContentBounds(gfx::Size(10, 10)); - tileLayer->setDrawsContent(true); - tileLayer->setSkipsDraw(false); - scoped_ptr<LayerTilingData> tilingData(LayerTilingData::create(gfx::Size(10, 10), LayerTilingData::NoBorderTexels)); - tilingData->setBounds(gfx::Size(10, 10)); - tileLayer->setTilingData(*tilingData); - tileLayer->pushTileProperties(0, 0, 1, gfx::Rect(0, 0, 10, 10), false); - rootLayer->addChild(tileLayer.PassAs<LayerImpl>()); - - scoped_ptr<TextureLayerImpl> textureLayer = TextureLayerImpl::create(m_hostImpl->activeTree(), layerId++); - textureLayer->setBounds(gfx::Size(10, 10)); - textureLayer->setAnchorPoint(gfx::PointF(0, 0)); - textureLayer->setContentBounds(gfx::Size(10, 10)); - textureLayer->setDrawsContent(true); - textureLayer->setTextureId(StrictWebGraphicsContext3D::kExternalTextureId); - rootLayer->addChild(textureLayer.PassAs<LayerImpl>()); - - scoped_ptr<TiledLayerImpl> maskLayer = TiledLayerImpl::create(m_hostImpl->activeTree(), layerId++); - maskLayer->setBounds(gfx::Size(10, 10)); - maskLayer->setAnchorPoint(gfx::PointF(0, 0)); - maskLayer->setContentBounds(gfx::Size(10, 10)); - maskLayer->setDrawsContent(true); - maskLayer->setSkipsDraw(false); - maskLayer->setTilingData(*tilingData); - maskLayer->pushTileProperties(0, 0, 1, gfx::Rect(0, 0, 10, 10), false); - - scoped_ptr<TextureLayerImpl> textureLayerWithMask = TextureLayerImpl::create(m_hostImpl->activeTree(), layerId++); - textureLayerWithMask->setBounds(gfx::Size(10, 10)); - textureLayerWithMask->setAnchorPoint(gfx::PointF(0, 0)); - textureLayerWithMask->setContentBounds(gfx::Size(10, 10)); - textureLayerWithMask->setDrawsContent(true); - textureLayerWithMask->setTextureId(StrictWebGraphicsContext3D::kExternalTextureId); - textureLayerWithMask->setMaskLayer(maskLayer.PassAs<LayerImpl>()); - rootLayer->addChild(textureLayerWithMask.PassAs<LayerImpl>()); - - FakeVideoFrame videoFrame(VideoFrame::CreateColorFrame(gfx::Size(4, 4), - 0x80, 0x80, 0x80, - base::TimeDelta())); - VideoLayerImpl::FrameUnwrapper unwrapper = - base::Bind(FakeVideoFrame::toVideoFrame); - FakeVideoFrameProvider provider; - provider.setFrame(&videoFrame); - scoped_ptr<VideoLayerImpl> videoLayer = VideoLayerImpl::create(m_hostImpl->activeTree(), layerId++, &provider, unwrapper); - videoLayer->setBounds(gfx::Size(10, 10)); - videoLayer->setAnchorPoint(gfx::PointF(0, 0)); - videoLayer->setContentBounds(gfx::Size(10, 10)); - videoLayer->setDrawsContent(true); - rootLayer->addChild(videoLayer.PassAs<LayerImpl>()); - - FakeVideoFrameProvider providerScaled; - scoped_ptr<VideoLayerImpl> videoLayerScaled = VideoLayerImpl::create(m_hostImpl->activeTree(), layerId++, &providerScaled, unwrapper); - videoLayerScaled->setBounds(gfx::Size(10, 10)); - videoLayerScaled->setAnchorPoint(gfx::PointF(0, 0)); - videoLayerScaled->setContentBounds(gfx::Size(10, 10)); - videoLayerScaled->setDrawsContent(true); - rootLayer->addChild(videoLayerScaled.PassAs<LayerImpl>()); - - FakeVideoFrameProvider hwProvider; - scoped_ptr<VideoLayerImpl> hwVideoLayer = VideoLayerImpl::create(m_hostImpl->activeTree(), layerId++, &hwProvider, unwrapper); - hwVideoLayer->setBounds(gfx::Size(10, 10)); - hwVideoLayer->setAnchorPoint(gfx::PointF(0, 0)); - hwVideoLayer->setContentBounds(gfx::Size(10, 10)); - hwVideoLayer->setDrawsContent(true); - rootLayer->addChild(hwVideoLayer.PassAs<LayerImpl>()); - - scoped_ptr<IOSurfaceLayerImpl> ioSurfaceLayer = IOSurfaceLayerImpl::create(m_hostImpl->activeTree(), layerId++); - ioSurfaceLayer->setBounds(gfx::Size(10, 10)); - ioSurfaceLayer->setAnchorPoint(gfx::PointF(0, 0)); - ioSurfaceLayer->setContentBounds(gfx::Size(10, 10)); - ioSurfaceLayer->setDrawsContent(true); - ioSurfaceLayer->setIOSurfaceProperties(1, gfx::Size(10, 10)); - rootLayer->addChild(ioSurfaceLayer.PassAs<LayerImpl>()); - - scoped_ptr<HeadsUpDisplayLayerImpl> hudLayer = HeadsUpDisplayLayerImpl::create(m_hostImpl->activeTree(), layerId++); - hudLayer->setBounds(gfx::Size(10, 10)); - hudLayer->setAnchorPoint(gfx::PointF(0, 0)); - hudLayer->setContentBounds(gfx::Size(10, 10)); - hudLayer->setDrawsContent(true); - rootLayer->addChild(hudLayer.PassAs<LayerImpl>()); - - scoped_ptr<FakeScrollbarLayerImpl> scrollbarLayer(FakeScrollbarLayerImpl::create(m_hostImpl->activeTree(), layerId++)); - scrollbarLayer->setBounds(gfx::Size(10, 10)); - scrollbarLayer->setContentBounds(gfx::Size(10, 10)); - scrollbarLayer->setDrawsContent(true); - scrollbarLayer->createResources(m_hostImpl->resourceProvider()); - rootLayer->addChild(scrollbarLayer.PassAs<LayerImpl>()); - - scoped_ptr<DelegatedRendererLayerImpl> delegatedRendererLayer(DelegatedRendererLayerImpl::create(m_hostImpl->activeTree(), layerId++)); - delegatedRendererLayer->setBounds(gfx::Size(10, 10)); - delegatedRendererLayer->setContentBounds(gfx::Size(10, 10)); - delegatedRendererLayer->setDrawsContent(true); - ScopedPtrVector<RenderPass> passList; - passList.append(createRenderPassWithResource(m_hostImpl->resourceProvider())); - delegatedRendererLayer->setRenderPasses(passList); - EXPECT_TRUE(passList.isEmpty()); - rootLayer->addChild(delegatedRendererLayer.PassAs<LayerImpl>()); - - // Use a context that supports IOSurfaces - m_hostImpl->initializeRenderer(FakeOutputSurface::Create3d(scoped_ptr<WebKit::WebGraphicsContext3D>(new FakeWebGraphicsContext3DWithIOSurface)).PassAs<OutputSurface>()); - - FakeVideoFrame hwVideoFrame( - VideoFrame::WrapNativeTexture( - m_hostImpl->resourceProvider()->graphicsContext3D()->createTexture(), - GL_TEXTURE_2D, - gfx::Size(4, 4), gfx::Rect(0, 0, 4, 4), gfx::Size(4, 4), base::TimeDelta(), - VideoFrame::ReadPixelsCB(), base::Closure())); - hwProvider.setFrame(&hwVideoFrame); - - FakeVideoFrame videoFrameScaled( - VideoFrame::WrapNativeTexture( - m_hostImpl->resourceProvider()->graphicsContext3D()->createTexture(), - GL_TEXTURE_2D, - gfx::Size(4, 4), gfx::Rect(0, 0, 3, 2), gfx::Size(4, 4), base::TimeDelta(), - VideoFrame::ReadPixelsCB(), base::Closure())); - providerScaled.setFrame(&videoFrameScaled); - - m_hostImpl->setRootLayer(rootLayer.Pass()); - - LayerTreeHostImpl::FrameData frame; - EXPECT_TRUE(m_hostImpl->prepareToDraw(frame)); - m_hostImpl->drawLayers(frame); - m_hostImpl->didDrawAllLayers(frame); - m_hostImpl->swapBuffers(); - - unsigned numResources = m_hostImpl->resourceProvider()->numResources(); - - // Lose the WebKit::WebGraphicsContext3D, replacing it with a StrictWebGraphicsContext3DWithIOSurface, - // that will warn if any resource from the previous context gets used. - m_hostImpl->initializeRenderer(FakeOutputSurface::Create3d(scoped_ptr<WebKit::WebGraphicsContext3D>(new StrictWebGraphicsContext3DWithIOSurface)).PassAs<OutputSurface>()); - - // Create dummy resources so that looking up an old resource will get an - // invalid texture id mapping. - for (unsigned i = 0; i < numResources; ++i) - m_hostImpl->resourceProvider()->createResourceFromExternalTexture(StrictWebGraphicsContext3D::kExternalTextureId); - - // The WebKit::WebVideoFrameProvider is expected to recreate its textures after a - // lost output surface (or not serve a frame). - hwProvider.setFrame(0); - providerScaled.setFrame(0); - - EXPECT_TRUE(m_hostImpl->prepareToDraw(frame)); - m_hostImpl->drawLayers(frame); - m_hostImpl->didDrawAllLayers(frame); - m_hostImpl->swapBuffers(); - - FakeVideoFrame hwVideoFrame2( - VideoFrame::WrapNativeTexture( - m_hostImpl->resourceProvider()->graphicsContext3D()->createTexture(), - GL_TEXTURE_2D, - gfx::Size(4, 4), gfx::Rect(0, 0, 4, 4), gfx::Size(4, 4), base::TimeDelta(), - VideoFrame::ReadPixelsCB(), base::Closure())); - hwProvider.setFrame(&hwVideoFrame2); - - EXPECT_TRUE(m_hostImpl->prepareToDraw(frame)); - m_hostImpl->drawLayers(frame); - m_hostImpl->didDrawAllLayers(frame); - m_hostImpl->swapBuffers(); -} - // Fake WebKit::WebGraphicsContext3D that tracks the number of textures in use. class TrackingWebGraphicsContext3D : public FakeWebGraphicsContext3D { public: @@ -2998,35 +2492,39 @@ private: unsigned m_numTextures; }; +static unsigned createResourceId(ResourceProvider* resourceProvider) +{ + return resourceProvider->createResource( + gfx::Size(20, 12), + resourceProvider->bestTextureFormat(), + ResourceProvider::TextureUsageAny); +} + +static unsigned createTextureId(ResourceProvider* resourceProvider) +{ + return ResourceProvider::ScopedReadLockGL( + resourceProvider, createResourceId(resourceProvider)).textureId(); +} + TEST_P(LayerTreeHostImplTest, layersFreeTextures) { + scoped_ptr<FakeWebGraphicsContext3D> context = + FakeWebGraphicsContext3D::Create(); + FakeWebGraphicsContext3D* context3d = context.get(); + scoped_ptr<OutputSurface> outputSurface = FakeOutputSurface::Create3d( + context.PassAs<WebKit::WebGraphicsContext3D>()).PassAs<OutputSurface>(); + m_hostImpl->initializeRenderer(outputSurface.Pass()); + scoped_ptr<LayerImpl> rootLayer(LayerImpl::create(m_hostImpl->activeTree(), 1)); rootLayer->setBounds(gfx::Size(10, 10)); rootLayer->setAnchorPoint(gfx::PointF(0, 0)); - scoped_ptr<TiledLayerImpl> tileLayer = TiledLayerImpl::create(m_hostImpl->activeTree(), 2); - tileLayer->setBounds(gfx::Size(10, 10)); - tileLayer->setAnchorPoint(gfx::PointF(0, 0)); - tileLayer->setContentBounds(gfx::Size(10, 10)); - tileLayer->setDrawsContent(true); - tileLayer->setSkipsDraw(false); - scoped_ptr<LayerTilingData> tilingData(LayerTilingData::create(gfx::Size(10, 10), LayerTilingData::NoBorderTexels)); - tilingData->setBounds(gfx::Size(10, 10)); - tileLayer->setTilingData(*tilingData); - tileLayer->pushTileProperties(0, 0, 1, gfx::Rect(0, 0, 10, 10), false); - rootLayer->addChild(tileLayer.PassAs<LayerImpl>()); - - scoped_ptr<TextureLayerImpl> textureLayer = TextureLayerImpl::create(m_hostImpl->activeTree(), 3); - textureLayer->setBounds(gfx::Size(10, 10)); - textureLayer->setAnchorPoint(gfx::PointF(0, 0)); - textureLayer->setContentBounds(gfx::Size(10, 10)); - textureLayer->setDrawsContent(true); - textureLayer->setTextureId(1); - rootLayer->addChild(textureLayer.PassAs<LayerImpl>()); - + FakeVideoFrame softwareFrame(media::VideoFrame::CreateColorFrame( + gfx::Size(4, 4), 0x80, 0x80, 0x80, base::TimeDelta())); VideoLayerImpl::FrameUnwrapper unwrapper = - base::Bind(FakeVideoFrame::toVideoFrame); + base::Bind(FakeVideoFrame::ToVideoFrame); FakeVideoFrameProvider provider; + provider.set_frame(&softwareFrame); scoped_ptr<VideoLayerImpl> videoLayer = VideoLayerImpl::create(m_hostImpl->activeTree(), 4, &provider, unwrapper); videoLayer->setBounds(gfx::Size(10, 10)); videoLayer->setAnchorPoint(gfx::PointF(0, 0)); @@ -3042,25 +2540,22 @@ TEST_P(LayerTreeHostImplTest, layersFreeTextures) ioSurfaceLayer->setIOSurfaceProperties(1, gfx::Size(10, 10)); rootLayer->addChild(ioSurfaceLayer.PassAs<LayerImpl>()); - // Lose the WebGraphicsContext3D, replacing it with a TrackingWebGraphicsContext3D (which the LayerTreeHostImpl takes ownership of). - scoped_ptr<OutputSurface> outputSurface(FakeOutputSurface::Create3d(scoped_ptr<WebKit::WebGraphicsContext3D>(new TrackingWebGraphicsContext3D))); - TrackingWebGraphicsContext3D* trackingWebGraphicsContext3D = static_cast<TrackingWebGraphicsContext3D*>(outputSurface->Context3D()); - m_hostImpl->initializeRenderer(outputSurface.Pass()); - m_hostImpl->setRootLayer(rootLayer.Pass()); + EXPECT_EQ(0u, context3d->NumTextures()); + LayerTreeHostImpl::FrameData frame; EXPECT_TRUE(m_hostImpl->prepareToDraw(frame)); m_hostImpl->drawLayers(frame); m_hostImpl->didDrawAllLayers(frame); m_hostImpl->swapBuffers(); - EXPECT_GT(trackingWebGraphicsContext3D->numTextures(), 0u); + EXPECT_GT(context3d->NumTextures(), 0u); // Kill the layer tree. m_hostImpl->setRootLayer(LayerImpl::create(m_hostImpl->activeTree(), 100)); // There should be no textures left in use after. - EXPECT_EQ(0u, trackingWebGraphicsContext3D->numTextures()); + EXPECT_EQ(0u, context3d->NumTextures()); } class MockDrawQuadsToFillScreenContext : public FakeWebGraphicsContext3D { diff --git a/cc/layer_tree_host_unittest.cc b/cc/layer_tree_host_unittest.cc index 7e43aed..dd7bb1d 100644 --- a/cc/layer_tree_host_unittest.cc +++ b/cc/layer_tree_host_unittest.cc @@ -1009,7 +1009,10 @@ public: m_layer = FakeContentLayer::Create(&m_client); m_layer->setBounds(gfx::Size(10, 20)); - m_scrollbar = FakeScrollbarLayer::Create(true, m_layer->id()); + bool paint_scrollbar = true; + bool has_thumb = false; + m_scrollbar = FakeScrollbarLayer::Create( + paint_scrollbar, has_thumb, m_layer->id()); m_scrollbar->setPosition(gfx::Point(0, 10)); m_scrollbar->setBounds(gfx::Size(10, 10)); @@ -1130,13 +1133,16 @@ public: m_child->setPosition(gfx::Point(0, 10)); m_child->setBounds(gfx::Size(3, 10)); - m_scrollbarWithPaints = - FakeScrollbarLayer::Create(true, m_parent->id()); + bool paint_scrollbar = true; + bool has_thumb = false; + m_scrollbarWithPaints = FakeScrollbarLayer::Create( + paint_scrollbar, has_thumb, m_parent->id()); m_scrollbarWithPaints->setPosition(gfx::Point(3, 10)); m_scrollbarWithPaints->setBounds(gfx::Size(3, 10)); - m_scrollbarWithoutPaints = - FakeScrollbarLayer::Create(false, m_parent->id()); + paint_scrollbar = false; + m_scrollbarWithoutPaints = FakeScrollbarLayer::Create( + paint_scrollbar, has_thumb, m_parent->id()); m_scrollbarWithoutPaints->setPosition(gfx::Point(6, 10)); m_scrollbarWithoutPaints->setBounds(gfx::Size(3, 10)); @@ -1306,74 +1312,6 @@ TEST_F(LayerTreeHostTestAtomicCommitWithPartialUpdate, runMultiThread) runTest(true); } -// A loseOutputSurface(1) should lead to a didRecreateOutputSurface(true) -class LayerTreeHostTestSetSingleLostContext : public LayerTreeHostTest { -public: - LayerTreeHostTestSetSingleLostContext() - { - } - - virtual void beginTest() OVERRIDE - { - postSetNeedsCommitToMainThread(); - } - - virtual void didCommitAndDrawFrame() OVERRIDE - { - m_layerTreeHost->loseOutputSurface(1); - } - - virtual void didRecreateOutputSurface(bool succeeded) OVERRIDE - { - EXPECT_TRUE(succeeded); - endTest(); - } - - virtual void afterTest() OVERRIDE - { - } -}; - -TEST_F(LayerTreeHostTestSetSingleLostContext, runMultiThread) -{ - runTest(true); -} - -// A loseOutputSurface(10) should lead to a didRecreateOutputSurface(false), and -// a finishAllRendering() should not hang. -class LayerTreeHostTestSetRepeatedLostContext : public LayerTreeHostTest { -public: - LayerTreeHostTestSetRepeatedLostContext() - { - } - - virtual void beginTest() OVERRIDE - { - postSetNeedsCommitToMainThread(); - } - - virtual void didCommitAndDrawFrame() OVERRIDE - { - m_layerTreeHost->loseOutputSurface(10); - } - - virtual void didRecreateOutputSurface(bool succeeded) OVERRIDE - { - EXPECT_FALSE(succeeded); - m_layerTreeHost->finishAllRendering(); - endTest(); - } - - virtual void afterTest() OVERRIDE - { - } -}; - -TEST_F(LayerTreeHostTestSetRepeatedLostContext, runMultiThread) -{ - runTest(true); -} - class LayerTreeHostTestFinishAllRendering : public LayerTreeHostTest { public: LayerTreeHostTestFinishAllRendering() @@ -1749,176 +1687,6 @@ TEST_F(LayerTreeHostTestEvictTextures, runMultiThread) runTest(true); } -class LayerTreeHostTestLostContextAfterEvictTextures : public LayerTreeHostTest { -public: - LayerTreeHostTestLostContextAfterEvictTextures() - : m_layer(EvictionTestLayer::create()) - , m_implForEvictTextures(0) - , m_numCommits(0) - { - } - - virtual void beginTest() OVERRIDE - { - m_layerTreeHost->setRootLayer(m_layer); - m_layerTreeHost->setViewportSize(gfx::Size(10, 20), gfx::Size(10, 20)); - - gfx::Transform identityMatrix; - setLayerPropertiesForTesting(m_layer.get(), 0, identityMatrix, gfx::PointF(0, 0), gfx::PointF(0, 0), gfx::Size(10, 20), true); - - postSetNeedsCommitToMainThread(); - } - - void postEvictTextures() - { - if (implThread()) { - implThread()->postTask(base::Bind(&LayerTreeHostTestLostContextAfterEvictTextures::evictTexturesOnImplThread, - base::Unretained(this))); - } else { - DebugScopedSetImplThread impl(proxy()); - evictTexturesOnImplThread(); - } - } - - void evictTexturesOnImplThread() - { - DCHECK(m_implForEvictTextures); - m_implForEvictTextures->enforceManagedMemoryPolicy(ManagedMemoryPolicy(0)); - } - - // Commit 1: Just commit and draw normally, then at the end, set ourselves - // invisible (to prevent a commit that would recreate textures after - // eviction, before the context recovery), and post a task that will evict - // textures, then cause the context to be lost, and then set ourselves - // visible again (to allow commits, since that's what causes context - // recovery in single thread). - virtual void didCommitAndDrawFrame() OVERRIDE - { - ++m_numCommits; - switch (m_numCommits) { - case 1: - EXPECT_TRUE(m_layer->haveBackingTexture()); - m_layerTreeHost->setVisible(false); - postEvictTextures(); - m_layerTreeHost->loseOutputSurface(1); - m_layerTreeHost->setVisible(true); - break; - default: - break; - } - } - - virtual void commitCompleteOnThread(LayerTreeHostImpl* impl) OVERRIDE - { - m_implForEvictTextures = impl; - } - - virtual void didRecreateOutputSurface(bool succeeded) OVERRIDE - { - EXPECT_TRUE(succeeded); - endTest(); - } - - virtual void afterTest() OVERRIDE - { - } - -private: - FakeContentLayerClient m_client; - scoped_refptr<EvictionTestLayer> m_layer; - LayerTreeHostImpl* m_implForEvictTextures; - int m_numCommits; -}; - -SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestLostContextAfterEvictTextures) - -class FakeWebGraphicsContext3DWithEndQueryCausingLostContext : public FakeWebGraphicsContext3D { -public: - static scoped_ptr<FakeWebGraphicsContext3DWithEndQueryCausingLostContext> create(Attributes attrs) - { - return make_scoped_ptr(new FakeWebGraphicsContext3DWithEndQueryCausingLostContext(attrs)); - } - - virtual void setContextLostCallback(WebGraphicsContextLostCallback* callback) { m_contextLostCallback = callback; } - virtual bool isContextLost() { return m_isContextLost; } - - virtual void beginQueryEXT(WebKit::WGC3Denum, WebKit::WebGLId) { } - virtual void endQueryEXT(WebKit::WGC3Denum) - { - // Lose context. - if (!m_isContextLost) { - m_contextLostCallback->onContextLost(); - m_isContextLost = true; - } - } - virtual void getQueryObjectuivEXT(WebKit::WebGLId, WebKit::WGC3Denum pname, WebKit::WGC3Duint* params) - { - // Context is lost. We need to behave as if result is available. - if (pname == GL_QUERY_RESULT_AVAILABLE_EXT) - *params = 1; - } - -private: - explicit FakeWebGraphicsContext3DWithEndQueryCausingLostContext(Attributes attrs) - : FakeWebGraphicsContext3D(attrs) - , m_contextLostCallback(0) - , m_isContextLost(false) { } - - WebGraphicsContextLostCallback* m_contextLostCallback; - bool m_isContextLost; -}; - -class LayerTreeHostTestLostContextWhileUpdatingResources : public LayerTreeHostTest { -public: - LayerTreeHostTestLostContextWhileUpdatingResources() - : m_parent(ContentLayerWithUpdateTracking::create(&m_client)) - , m_numChildren(50) - { - for (int i = 0; i < m_numChildren; i++) - m_children.push_back(ContentLayerWithUpdateTracking::create(&m_client)); - } - - virtual void beginTest() - { - m_layerTreeHost->setRootLayer(m_parent); - m_layerTreeHost->setViewportSize(gfx::Size(m_numChildren, 1), gfx::Size(m_numChildren, 1)); - - gfx::Transform identityMatrix; - setLayerPropertiesForTesting(m_parent.get(), 0, identityMatrix, gfx::PointF(0, 0), gfx::PointF(0, 0), gfx::Size(m_numChildren, 1), true); - for (int i = 0; i < m_numChildren; i++) - setLayerPropertiesForTesting(m_children[i].get(), m_parent.get(), identityMatrix, gfx::PointF(0, 0), gfx::PointF(i, 0), gfx::Size(1, 1), false); - - postSetNeedsCommitToMainThread(); - } - - virtual void commitCompleteOnThread(LayerTreeHostImpl* impl) - { - endTest(); - } - - virtual void layout() - { - m_parent->setNeedsDisplay(); - for (int i = 0; i < m_numChildren; i++) - m_children[i]->setNeedsDisplay(); - } - - virtual void afterTest() - { - } - -private: - FakeContentLayerClient m_client; - scoped_refptr<ContentLayerWithUpdateTracking> m_parent; - int m_numChildren; - std::vector<scoped_refptr<ContentLayerWithUpdateTracking> > m_children; -}; - -TEST_F(LayerTreeHostTestLostContextWhileUpdatingResources, runMultiThread) -{ - runTest(true); -} - class LayerTreeHostTestContinuousCommit : public LayerTreeHostTest { public: LayerTreeHostTestContinuousCommit() diff --git a/cc/layer_tree_host_unittest_context.cc b/cc/layer_tree_host_unittest_context.cc new file mode 100644 index 0000000..89846f4 --- /dev/null +++ b/cc/layer_tree_host_unittest_context.cc @@ -0,0 +1,791 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "cc/layer_tree_host.h" + +#include "base/basictypes.h" +#include "cc/content_layer.h" +#include "cc/delegated_renderer_layer.h" +#include "cc/delegated_renderer_layer_impl.h" +#include "cc/heads_up_display_layer.h" +#include "cc/io_surface_layer.h" +#include "cc/layer_impl.h" +#include "cc/layer_tree_host_impl.h" +#include "cc/layer_tree_impl.h" +#include "cc/scrollbar_layer.h" +#include "cc/single_thread_proxy.h" +#include "cc/test/fake_content_layer.h" +#include "cc/test/fake_content_layer_client.h" +#include "cc/test/fake_content_layer_impl.h" +#include "cc/test/fake_output_surface.h" +#include "cc/test/fake_scrollbar_theme_painter.h" +#include "cc/test/fake_video_frame.h" +#include "cc/test/fake_video_frame_provider.h" +#include "cc/test/fake_web_graphics_context_3d.h" +#include "cc/test/fake_web_scrollbar.h" +#include "cc/test/fake_web_scrollbar_theme_geometry.h" +#include "cc/test/layer_tree_test_common.h" +#include "cc/test/render_pass_test_common.h" +#include "cc/texture_layer.h" +#include "cc/video_layer.h" +#include "cc/video_layer_impl.h" +#include "media/base/media.h" + +using media::VideoFrame; +using WebKit::WebGraphicsContext3D; + +namespace cc { +namespace { + +// These tests deal with losing the 3d graphics context. +class LayerTreeHostContextTest : public ThreadedTest { + public: + LayerTreeHostContextTest() + : ThreadedTest(), + context3d_(NULL), + times_to_fail_create_(0), + times_to_create_and_lose_(0), + times_to_lose_during_commit_(0), + times_to_repeat_loss_(0), + times_to_fail_recreate_(0) { + media::InitializeMediaLibraryForTesting(); + } + + void LoseContext() { + context3d_->loseContextCHROMIUM(); + context3d_ = NULL; + } + + virtual scoped_ptr<FakeWebGraphicsContext3D> CreateContext3d() { + return FakeWebGraphicsContext3D::Create(); + } + + virtual scoped_ptr<OutputSurface> createOutputSurface() OVERRIDE { + if (times_to_fail_create_) { + --times_to_fail_create_; + return scoped_ptr<OutputSurface>(); + } + + scoped_ptr<FakeWebGraphicsContext3D> context3d = CreateContext3d(); + context3d_ = context3d.get(); + + if (times_to_create_and_lose_) { + --times_to_create_and_lose_; + // Make the context get lost during reinitialization. + // The number of times MakeCurrent succeeds is not important, and + // can be changed if needed to make this pass with future changes. + context3d_->set_times_make_current_succeeds(2); + } + + return FakeOutputSurface::Create3d( + context3d.PassAs<WebGraphicsContext3D>()).PassAs<OutputSurface>(); + } + + virtual void commitCompleteOnThread(LayerTreeHostImpl *host_impl) OVERRIDE { + if (!times_to_lose_during_commit_) + return; + --times_to_lose_during_commit_; + LoseContext(); + + times_to_create_and_lose_ = times_to_repeat_loss_; + times_to_repeat_loss_ = 0; + times_to_fail_create_ = times_to_fail_recreate_; + times_to_fail_recreate_ = 0; + } + + protected: + FakeWebGraphicsContext3D* context3d_; + int times_to_fail_create_; + int times_to_create_and_lose_; + int times_to_lose_during_commit_; + int times_to_repeat_loss_; + int times_to_fail_recreate_; +}; + +class LayerTreeHostContextTestLostContextSucceeds : + public LayerTreeHostContextTest { + public: + LayerTreeHostContextTestLostContextSucceeds() + : LayerTreeHostContextTest(), + test_case_(0), + num_losses_(0) { + } + + virtual void beginTest() OVERRIDE { + postSetNeedsCommitToMainThread(); + } + + virtual void didRecreateOutputSurface(bool succeeded) OVERRIDE { + EXPECT_TRUE(succeeded); + ++num_losses_; + } + + virtual void afterTest() OVERRIDE { + EXPECT_EQ(3, test_case_); + EXPECT_EQ(3, num_losses_); + } + + bool SourceFrameHasContextLoss(int source_frame) const { + return source_frame % 2 == 1; + } + + virtual void didCommitAndDrawFrame() OVERRIDE { + // If the last frame had a context loss, then we'll commit again to + // recover. + if (SourceFrameHasContextLoss(m_layerTreeHost->commitNumber()) - 1) + return; + + if (NextTestCase()) + m_layerTreeHost->setNeedsCommit(); + else + endTest(); + } + + bool NextTestCase() { + static const TestCase kTests[] = { + // Losing the context and failing to recreate it (or losing it again + // immediately) a small number of times should succeed. + { 1, // times_to_lose_during_commit + 0, // times_to_repeat_loss + 0, // times_to_fail_recreate + }, + { 1, + 3, // times_to_repeat_loss + 0, // times_to_fail_recreate + }, + { 1, + 0, // times_to_repeat_loss + 3, // times_to_fail_recreate + }, + }; + + if (test_case_ >= arraysize(kTests)) + return false; + + times_to_lose_during_commit_ = + kTests[test_case_].times_to_lose_during_commit; + times_to_repeat_loss_ = kTests[test_case_].times_to_repeat_loss; + times_to_fail_recreate_ = kTests[test_case_].times_to_fail_recreate; + ++test_case_; + return true; + } + + struct TestCase { + int times_to_lose_during_commit; + int times_to_repeat_loss; + int times_to_fail_recreate; + }; + + private: + size_t test_case_; + int num_losses_; +}; + +SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostContextTestLostContextSucceeds) + +class LayerTreeHostContextTestLostContextSucceedsWithContent : + public LayerTreeHostContextTestLostContextSucceeds { + public: + + LayerTreeHostContextTestLostContextSucceedsWithContent() + : LayerTreeHostContextTestLostContextSucceeds() { + } + + virtual void setupTree() OVERRIDE { + scoped_refptr<Layer> root_ = Layer::create(); + root_->setBounds(gfx::Size(10, 10)); + root_->setAnchorPoint(gfx::PointF()); + root_->setIsDrawable(true); + + scoped_refptr<FakeContentLayer> content_ = + FakeContentLayer::Create(&client_); + content_->setBounds(gfx::Size(10, 10)); + content_->setAnchorPoint(gfx::PointF()); + content_->setIsDrawable(true); + if (use_surface_) + content_->setForceRenderSurface(true); + root_->addChild(content_); + + m_layerTreeHost->setRootLayer(root_); + LayerTreeHostContextTest::setupTree(); + } + + virtual void drawLayersOnThread(LayerTreeHostImpl* host_impl) { + FakeContentLayerImpl* content_impl = static_cast<FakeContentLayerImpl*>( + host_impl->rootLayer()->children()[0]); + // Even though the context was lost, we should have a resource. The + // FakeWebGraphicsContext3D ensures that this resource is created with + // the active context. + EXPECT_TRUE(content_impl->HaveResourceForTileAt(0, 0)); + } + + protected: + bool use_surface_; + FakeContentLayerClient client_; + scoped_refptr<Layer> root_; + scoped_refptr<ContentLayer> content_; +}; + +TEST_F(LayerTreeHostContextTestLostContextSucceedsWithContent, + NoSurface_SingleThread) { + use_surface_ = false; + runTest(false); +} + +TEST_F(LayerTreeHostContextTestLostContextSucceedsWithContent, + NoSurface_MultiThread) { + use_surface_ = false; + runTest(true); +} + +TEST_F(LayerTreeHostContextTestLostContextSucceedsWithContent, + WithSurface_SingleThread) { + use_surface_ = true; + runTest(false); +} + +TEST_F(LayerTreeHostContextTestLostContextSucceedsWithContent, + WithSurface_MultiThread) { + use_surface_ = true; + runTest(true); +} + +class LayerTreeHostContextTestLostContextFails : + public LayerTreeHostContextTest { + public: + LayerTreeHostContextTestLostContextFails() + : LayerTreeHostContextTest(), + num_commits_(0) { + times_to_lose_during_commit_ = 1; + } + + virtual void beginTest() OVERRIDE { + postSetNeedsCommitToMainThread(); + } + + virtual void didRecreateOutputSurface(bool succeeded) OVERRIDE { + EXPECT_FALSE(succeeded); + endTest(); + } + + virtual void commitCompleteOnThread(LayerTreeHostImpl* host_impl) OVERRIDE { + LayerTreeHostContextTest::commitCompleteOnThread(host_impl); + + ++num_commits_; + if (num_commits_ == 1) { + // When the context is ok, we should have these things. + EXPECT_TRUE(host_impl->outputSurface()); + EXPECT_TRUE(host_impl->renderer()); + EXPECT_TRUE(host_impl->resourceProvider()); + return; + } + + // When context recreation fails we shouldn't be left with any of them. + EXPECT_FALSE(host_impl->outputSurface()); + EXPECT_FALSE(host_impl->renderer()); + EXPECT_FALSE(host_impl->resourceProvider()); + } + + virtual void afterTest() OVERRIDE {} + + private: + int num_commits_; +}; + +TEST_F(LayerTreeHostContextTestLostContextFails, RepeatLoss100_SingleThread) { + times_to_repeat_loss_ = 100; + times_to_fail_recreate_ = 0; + runTest(false); +} + +TEST_F(LayerTreeHostContextTestLostContextFails, RepeatLoss100_MultiThread) { + times_to_repeat_loss_ = 100; + times_to_fail_recreate_ = 0; + runTest(true); +} + +TEST_F(LayerTreeHostContextTestLostContextFails, FailRecreate100_SingleThread) { + times_to_repeat_loss_ = 0; + times_to_fail_recreate_ = 100; + runTest(false); +} + +TEST_F(LayerTreeHostContextTestLostContextFails, FailRecreate100_MultiThread) { + times_to_repeat_loss_ = 0; + times_to_fail_recreate_ = 100; + runTest(true); +} + +class LayerTreeHostContextTestFinishAllRenderingAfterLoss : + public LayerTreeHostContextTest { + public: + virtual void beginTest() OVERRIDE { + // Lose the context until the compositor gives up on it. + times_to_lose_during_commit_ = 1; + times_to_repeat_loss_ = 10; + postSetNeedsCommitToMainThread(); + } + + virtual void didRecreateOutputSurface(bool succeeded) OVERRIDE { + EXPECT_FALSE(succeeded); + m_layerTreeHost->finishAllRendering(); + endTest(); + } + + virtual void afterTest() OVERRIDE {} +}; + +SINGLE_AND_MULTI_THREAD_TEST_F( + LayerTreeHostContextTestFinishAllRenderingAfterLoss) + +class LayerTreeHostContextTestLostContextAndEvictTextures : + public LayerTreeHostContextTest { + public: + LayerTreeHostContextTestLostContextAndEvictTextures() + : LayerTreeHostContextTest(), + layer_(FakeContentLayer::Create(&client_)), + impl_host_(0), + num_commits_(0) { + } + + virtual void setupTree() OVERRIDE { + layer_->setBounds(gfx::Size(10, 20)); + m_layerTreeHost->setRootLayer(layer_); + LayerTreeHostContextTest::setupTree(); + } + + virtual void beginTest() OVERRIDE { + postSetNeedsCommitToMainThread(); + } + + void PostEvictTextures() { + if (implThread()) { + implThread()->postTask( + base::Bind( + &LayerTreeHostContextTestLostContextAndEvictTextures:: + EvictTexturesOnImplThread, + base::Unretained(this))); + } else { + DebugScopedSetImplThread impl(proxy()); + EvictTexturesOnImplThread(); + } + } + + void EvictTexturesOnImplThread() { + impl_host_->enforceManagedMemoryPolicy(ManagedMemoryPolicy(0)); + if (lose_after_evict_) + LoseContext(); + } + + virtual void didCommitAndDrawFrame() OVERRIDE { + if (num_commits_ > 1) + return; + EXPECT_TRUE(layer_->HaveBackingAt(0, 0)); + PostEvictTextures(); + } + + virtual void commitCompleteOnThread(LayerTreeHostImpl* impl) OVERRIDE { + if (num_commits_ > 1) + return; + ++num_commits_; + if (!lose_after_evict_) + LoseContext(); + impl_host_ = impl; + } + + virtual void didRecreateOutputSurface(bool succeeded) OVERRIDE { + EXPECT_TRUE(succeeded); + endTest(); + } + + virtual void afterTest() OVERRIDE {} + + protected: + bool lose_after_evict_; + FakeContentLayerClient client_; + scoped_refptr<FakeContentLayer> layer_; + LayerTreeHostImpl* impl_host_; + int num_commits_; +}; + +TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures, + LoseAfterEvict_SingleThread) { + lose_after_evict_ = true; + runTest(false); +} + +TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures, + LoseAfterEvict_MultiThread) { + lose_after_evict_ = true; + runTest(true); +} + +TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures, + LoseBeforeEvict_SingleThread) { + lose_after_evict_ = false; + runTest(false); +} + +TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures, + LoseBeforeEvict_MultiThread) { + lose_after_evict_ = false; + runTest(true); +} + +class LayerTreeHostContextTestLostContextWhileUpdatingResources : + public LayerTreeHostContextTest { + public: + LayerTreeHostContextTestLostContextWhileUpdatingResources() + : parent_(FakeContentLayer::Create(&client_)), + num_children_(50), + times_to_lose_on_end_query_(3) { + } + + virtual scoped_ptr<FakeWebGraphicsContext3D> CreateContext3d() { + scoped_ptr<FakeWebGraphicsContext3D> context = + LayerTreeHostContextTest::CreateContext3d(); + if (times_to_lose_on_end_query_) { + --times_to_lose_on_end_query_; + context->set_times_end_query_succeeds(5); + } + return context.Pass(); + } + + virtual void setupTree() { + parent_->setBounds(gfx::Size(num_children_, 1)); + + for (int i = 0; i < num_children_; i++) { + scoped_refptr<FakeContentLayer> child = + FakeContentLayer::Create(&client_); + child->setPosition(gfx::PointF(i, 0.f)); + child->setBounds(gfx::Size(1, 1)); + parent_->addChild(child); + } + + m_layerTreeHost->setRootLayer(parent_); + LayerTreeHostContextTest::setupTree(); + } + + virtual void beginTest() { + postSetNeedsCommitToMainThread(); + } + + virtual void commitCompleteOnThread(LayerTreeHostImpl* impl) { + endTest(); + } + + virtual void didRecreateOutputSurface(bool succeeded) OVERRIDE { + EXPECT_TRUE(succeeded); + } + + virtual void afterTest() { + EXPECT_EQ(0, times_to_lose_on_end_query_); + } + + private: + FakeContentLayerClient client_; + scoped_refptr<FakeContentLayer> parent_; + int num_children_; + int times_to_lose_on_end_query_; +}; + +SINGLE_AND_MULTI_THREAD_TEST_F( + LayerTreeHostContextTestLostContextWhileUpdatingResources) + +class LayerTreeHostContextTestLayersNotified : + public LayerTreeHostContextTest { + public: + LayerTreeHostContextTestLayersNotified() + : LayerTreeHostContextTest(), + num_commits_(0) { + } + + virtual void setupTree() OVERRIDE { + root_ = FakeContentLayer::Create(&client_); + child_ = FakeContentLayer::Create(&client_); + grandchild_ = FakeContentLayer::Create(&client_); + + root_->addChild(child_); + child_->addChild(grandchild_); + + m_layerTreeHost->setRootLayer(root_); + LayerTreeHostContextTest::setupTree(); + } + + virtual void beginTest() OVERRIDE { + postSetNeedsCommitToMainThread(); + } + + virtual void commitCompleteOnThread(LayerTreeHostImpl* host_impl) OVERRIDE { + FakeContentLayerImpl* root = static_cast<FakeContentLayerImpl*>( + host_impl->rootLayer()); + FakeContentLayerImpl* child = static_cast<FakeContentLayerImpl*>( + root->children()[0]); + FakeContentLayerImpl* grandchild = static_cast<FakeContentLayerImpl*>( + child->children()[0]); + + ++num_commits_; + switch (num_commits_) { + case 1: + EXPECT_EQ(0u, root->lost_output_surface_count()); + EXPECT_EQ(0u, child->lost_output_surface_count()); + EXPECT_EQ(0u, grandchild->lost_output_surface_count()); + // Lose the context and struggle to recreate it. + LoseContext(); + times_to_fail_create_ = 1; + break; + case 2: + EXPECT_EQ(1u, root->lost_output_surface_count()); + EXPECT_EQ(1u, child->lost_output_surface_count()); + EXPECT_EQ(1u, grandchild->lost_output_surface_count()); + // Lose the context and again during recreate. + LoseContext(); + times_to_create_and_lose_ = 1; + break; + case 3: + EXPECT_EQ(3u, root->lost_output_surface_count()); + EXPECT_EQ(3u, child->lost_output_surface_count()); + EXPECT_EQ(3u, grandchild->lost_output_surface_count()); + endTest(); + break; + default: + NOTREACHED(); + } + } + + virtual void afterTest() OVERRIDE {} + + private: + int num_commits_; + + FakeContentLayerClient client_; + scoped_refptr<FakeContentLayer> root_; + scoped_refptr<FakeContentLayer> child_; + scoped_refptr<FakeContentLayer> grandchild_; +}; + +SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostContextTestLayersNotified) + +class LayerTreeHostContextTestDontUseLostResources : + public LayerTreeHostContextTest { + public: + virtual void setupTree() OVERRIDE { + context3d_->set_have_extension_io_surface(true); + context3d_->set_have_extension_egl_image(true); + + scoped_refptr<Layer> root_ = Layer::create(); + root_->setBounds(gfx::Size(10, 10)); + root_->setAnchorPoint(gfx::PointF()); + root_->setIsDrawable(true); + + scoped_refptr<DelegatedRendererLayer> delegated_ = + DelegatedRendererLayer::create(); + delegated_->setBounds(gfx::Size(10, 10)); + delegated_->setAnchorPoint(gfx::PointF()); + delegated_->setIsDrawable(true); + root_->addChild(delegated_); + + scoped_refptr<ContentLayer> content_ = ContentLayer::create(&client_); + content_->setBounds(gfx::Size(10, 10)); + content_->setAnchorPoint(gfx::PointF()); + content_->setIsDrawable(true); + root_->addChild(content_); + + scoped_refptr<TextureLayer> texture_ = TextureLayer::create(NULL); + texture_->setBounds(gfx::Size(10, 10)); + texture_->setAnchorPoint(gfx::PointF()); + texture_->setTextureId(FakeWebGraphicsContext3D::kExternalTextureId); + texture_->setIsDrawable(true); + root_->addChild(texture_); + + scoped_refptr<ContentLayer> mask_ = ContentLayer::create(&client_); + mask_->setBounds(gfx::Size(10, 10)); + mask_->setAnchorPoint(gfx::PointF()); + + scoped_refptr<ContentLayer> content_with_mask_ = + ContentLayer::create(&client_); + content_with_mask_->setBounds(gfx::Size(10, 10)); + content_with_mask_->setAnchorPoint(gfx::PointF()); + content_with_mask_->setIsDrawable(true); + content_with_mask_->setMaskLayer(mask_.get()); + root_->addChild(content_with_mask_); + + VideoLayerImpl::FrameUnwrapper unwrapper = + base::Bind(FakeVideoFrame::ToVideoFrame); + + scoped_refptr<VideoLayer> video_color_ = VideoLayer::create( + &color_frame_provider_, unwrapper); + video_color_->setBounds(gfx::Size(10, 10)); + video_color_->setAnchorPoint(gfx::PointF()); + video_color_->setIsDrawable(true); + root_->addChild(video_color_); + + scoped_refptr<VideoLayer> video_hw_ = VideoLayer::create( + &hw_frame_provider_, unwrapper); + video_hw_->setBounds(gfx::Size(10, 10)); + video_hw_->setAnchorPoint(gfx::PointF()); + video_hw_->setIsDrawable(true); + root_->addChild(video_hw_); + + scoped_refptr<VideoLayer> video_scaled_hw_ = VideoLayer::create( + &scaled_hw_frame_provider_, unwrapper); + video_scaled_hw_->setBounds(gfx::Size(10, 10)); + video_scaled_hw_->setAnchorPoint(gfx::PointF()); + video_scaled_hw_->setIsDrawable(true); + root_->addChild(video_scaled_hw_); + + scoped_refptr<IOSurfaceLayer> io_surface_ = IOSurfaceLayer::create(); + io_surface_->setBounds(gfx::Size(10, 10)); + io_surface_->setAnchorPoint(gfx::PointF()); + io_surface_->setIsDrawable(true); + io_surface_->setIOSurfaceProperties(1, gfx::Size(10, 10)); + root_->addChild(io_surface_); + + scoped_refptr<HeadsUpDisplayLayer> hud_ = HeadsUpDisplayLayer::create(); + hud_->setBounds(gfx::Size(10, 10)); + hud_->setAnchorPoint(gfx::PointF()); + hud_->setIsDrawable(true); + root_->addChild(hud_); + // Enable the hud. + LayerTreeDebugState debug_state; + debug_state.showFPSCounter = true; + m_layerTreeHost->setDebugState(debug_state); + + bool paint_scrollbar = true; + bool has_thumb = true; + scoped_refptr<ScrollbarLayer> scrollbar_ = ScrollbarLayer::create( + FakeWebScrollbar::create().PassAs<WebKit::WebScrollbar>(), + FakeScrollbarThemePainter::Create(paint_scrollbar) + .PassAs<ScrollbarThemePainter>(), + FakeWebScrollbarThemeGeometry::create(has_thumb) + .PassAs<WebKit::WebScrollbarThemeGeometry>(), + content_->id()); + scrollbar_->setBounds(gfx::Size(10, 10)); + scrollbar_->setAnchorPoint(gfx::PointF()); + scrollbar_->setIsDrawable(true); + root_->addChild(scrollbar_); + + m_layerTreeHost->setRootLayer(root_); + LayerTreeHostContextTest::setupTree(); + } + + virtual void beginTest() OVERRIDE { + postSetNeedsCommitToMainThread(); + } + + virtual void commitCompleteOnThread(LayerTreeHostImpl* host_impl) OVERRIDE { + ResourceProvider* resource_provider = host_impl->resourceProvider(); + + if (host_impl->activeTree()->source_frame_number() == 0) { + // Set up impl resources on the first commit. + + scoped_ptr<TestRenderPass> pass_for_quad = TestRenderPass::Create(); + pass_for_quad->SetNew( + // AppendOneOfEveryQuadType() makes a RenderPass quad with this id. + RenderPass::Id(1, 1), + gfx::Rect(0, 0, 10, 10), + gfx::Rect(0, 0, 10, 10), + gfx::Transform()); + + scoped_ptr<TestRenderPass> pass = TestRenderPass::Create(); + pass->SetNew( + RenderPass::Id(2, 1), + gfx::Rect(0, 0, 10, 10), + gfx::Rect(0, 0, 10, 10), + gfx::Transform()); + pass->AppendOneOfEveryQuadType(resource_provider); + + ScopedPtrVector<RenderPass> pass_list; + pass_list.append(pass_for_quad.PassAs<RenderPass>()); + pass_list.append(pass.PassAs<RenderPass>()); + + // First child is the delegated layer. + DelegatedRendererLayerImpl* delegated_impl = + static_cast<DelegatedRendererLayerImpl*>( + host_impl->rootLayer()->children()[0]); + delegated_impl->setRenderPasses(pass_list); + EXPECT_TRUE(pass_list.isEmpty()); + + color_video_frame_ = make_scoped_ptr(new FakeVideoFrame( + VideoFrame::CreateColorFrame( + gfx::Size(4, 4), 0x80, 0x80, 0x80, base::TimeDelta()))); + hw_video_frame_ = make_scoped_ptr(new FakeVideoFrame( + VideoFrame::WrapNativeTexture( + resource_provider->graphicsContext3D()->createTexture(), + GL_TEXTURE_2D, + gfx::Size(4, 4), gfx::Rect(0, 0, 4, 4), gfx::Size(4, 4), + base::TimeDelta(), + VideoFrame::ReadPixelsCB(), + base::Closure()))); + scaled_hw_video_frame_ = make_scoped_ptr(new FakeVideoFrame( + VideoFrame::WrapNativeTexture( + resource_provider->graphicsContext3D()->createTexture(), + GL_TEXTURE_2D, + gfx::Size(4, 4), gfx::Rect(0, 0, 3, 2), gfx::Size(4, 4), + base::TimeDelta(), + VideoFrame::ReadPixelsCB(), + base::Closure()))); + + color_frame_provider_.set_frame(color_video_frame_.get()); + hw_frame_provider_.set_frame(hw_video_frame_.get()); + scaled_hw_frame_provider_.set_frame(scaled_hw_video_frame_.get()); + return; + } + + if (host_impl->activeTree()->source_frame_number() == 3) { + // On the third commit we're recovering from context loss. Hardware + // video frames should not be reused by the VideoFrameProvider, but + // software frames can be. + hw_frame_provider_.set_frame(NULL); + scaled_hw_frame_provider_.set_frame(NULL); + } + } + + virtual bool prepareToDrawOnThread(LayerTreeHostImpl* host_impl) { + if (host_impl->activeTree()->source_frame_number() == 2) { + // Lose the context during draw on the second commit. This will cause + // a third commit to recover. + if (context3d_) + context3d_->set_times_bind_texture_succeeds(4); + } + return true; + } + + virtual void didCommitAndDrawFrame() OVERRIDE { + // End the test once we know the 3nd frame drew. + if (m_layerTreeHost->commitNumber() == 4) + endTest(); + } + + virtual void afterTest() OVERRIDE {} + + private: + FakeContentLayerClient client_; + + scoped_refptr<Layer> root_; + scoped_refptr<DelegatedRendererLayer> delegated_; + scoped_refptr<ContentLayer> content_; + scoped_refptr<TextureLayer> texture_; + scoped_refptr<ContentLayer> mask_; + scoped_refptr<ContentLayer> content_with_mask_; + scoped_refptr<VideoLayer> video_color_; + scoped_refptr<VideoLayer> video_hw_; + scoped_refptr<VideoLayer> video_scaled_hw_; + scoped_refptr<IOSurfaceLayer> io_surface_; + scoped_refptr<HeadsUpDisplayLayer> hud_; + scoped_refptr<ScrollbarLayer> scrollbar_; + + scoped_ptr<FakeVideoFrame> color_video_frame_; + scoped_ptr<FakeVideoFrame> hw_video_frame_; + scoped_ptr<FakeVideoFrame> scaled_hw_video_frame_; + + FakeVideoFrameProvider color_frame_provider_; + FakeVideoFrameProvider hw_frame_provider_; + FakeVideoFrameProvider scaled_hw_frame_provider_; +}; + +SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostContextTestDontUseLostResources) + +} // namespace +} // namespace cc diff --git a/cc/layer_tree_host_unittest_scroll.cc b/cc/layer_tree_host_unittest_scroll.cc index 5d7a309..5c30a22 100644 --- a/cc/layer_tree_host_unittest_scroll.cc +++ b/cc/layer_tree_host_unittest_scroll.cc @@ -241,11 +241,8 @@ class LayerTreeHostScrollTestCaseWithChild : public LayerTreeHostScrollTest, public WebKit::WebLayerScrollClient { public: - LayerTreeHostScrollTestCaseWithChild( - float device_scale_factor, bool scroll_child_layer) - : device_scale_factor_(device_scale_factor), - scroll_child_layer_(scroll_child_layer), - initial_offset_(10, 20), + LayerTreeHostScrollTestCaseWithChild() + : initial_offset_(10, 20), javascript_scroll_(40, 5), scroll_amount_(2, -1), num_scrolls_(0) { @@ -436,9 +433,10 @@ class LayerTreeHostScrollTestCaseWithChild : } } - private: + protected: float device_scale_factor_; bool scroll_child_layer_; + gfx::Vector2d initial_offset_; gfx::Vector2d javascript_scroll_; gfx::Vector2d scroll_amount_; @@ -453,24 +451,44 @@ class LayerTreeHostScrollTestCaseWithChild : scoped_refptr<Layer> expected_no_scroll_layer_; }; -MULTI_THREAD_TEST_P2(LayerTreeHostScrollTestCaseWithChild, - DeviceScaleFactor1, 1.0f, - ScrollChild, true) -MULTI_THREAD_TEST_P2(LayerTreeHostScrollTestCaseWithChild, - DeviceScaleFactor15, 1.5f, - ScrollChild, true) -MULTI_THREAD_TEST_P2(LayerTreeHostScrollTestCaseWithChild, - DeviceScaleFactor2, 2.0f, - ScrollChild, true) -MULTI_THREAD_TEST_P2(LayerTreeHostScrollTestCaseWithChild, - DeviceScaleFactor1, 1.0f, - ScrollRootScrollLayer, false) -MULTI_THREAD_TEST_P2(LayerTreeHostScrollTestCaseWithChild, - DeviceScaleFactor15, 1.5f, - ScrollRootScrollLayer, false) -MULTI_THREAD_TEST_P2(LayerTreeHostScrollTestCaseWithChild, - DeviceScaleFactor2, 2.0f, - ScrollRootScrollLayer, false) +TEST_F(LayerTreeHostScrollTestCaseWithChild, DeviceScaleFactor1_ScrollChild) { + device_scale_factor_ = 1.f; + scroll_child_layer_ = true; + runTest(true); +} + +TEST_F(LayerTreeHostScrollTestCaseWithChild, DeviceScaleFactor15_ScrollChild) { + device_scale_factor_ = 1.5f; + scroll_child_layer_ = true; + runTest(true); +} + +TEST_F(LayerTreeHostScrollTestCaseWithChild, DeviceScaleFactor2_ScrollChild) { + device_scale_factor_ = 2.f; + scroll_child_layer_ = true; + runTest(true); +} + +TEST_F(LayerTreeHostScrollTestCaseWithChild, + DeviceScaleFactor1_ScrollRootScrollLayer) { + device_scale_factor_ = 1.f; + scroll_child_layer_ = false; + runTest(true); +} + +TEST_F(LayerTreeHostScrollTestCaseWithChild, + DeviceScaleFactor15_ScrollRootScrollLayer) { + device_scale_factor_ = 1.5f; + scroll_child_layer_ = false; + runTest(true); +} + +TEST_F(LayerTreeHostScrollTestCaseWithChild, + DeviceScaleFactor2_ScrollRootScrollLayer) { + device_scale_factor_ = 2.f; + scroll_child_layer_ = false; + runTest(true); +} class ImplSidePaintingScrollTest : public LayerTreeHostScrollTest { public: diff --git a/cc/resource_provider_unittest.cc b/cc/resource_provider_unittest.cc index 0a737e5..869c518 100644 --- a/cc/resource_provider_unittest.cc +++ b/cc/resource_provider_unittest.cc @@ -563,6 +563,9 @@ class TextureStateTrackingContext : public FakeWebGraphicsContext3D { public: MOCK_METHOD2(bindTexture, void(WGC3Denum target, WebGLId texture)); MOCK_METHOD3(texParameteri, void(WGC3Denum target, WGC3Denum pname, WGC3Dint param)); + + // Force all textures to be "1" so we can test for them. + virtual WebKit::WebGLId NextTextureId() { return 1; } }; TEST_P(ResourceProviderTest, ScopedSampler) diff --git a/cc/scrollbar_layer_unittest.cc b/cc/scrollbar_layer_unittest.cc index 1c3bcfb..5dcda61 100644 --- a/cc/scrollbar_layer_unittest.cc +++ b/cc/scrollbar_layer_unittest.cc @@ -29,7 +29,7 @@ scoped_ptr<LayerImpl> layerImplForScrollAreaAndScrollbar( { scoped_refptr<Layer> layerTreeRoot = Layer::create(); scoped_refptr<Layer> child1 = Layer::create(); - scoped_refptr<Layer> child2 = ScrollbarLayer::create(scrollbar.Pass(), FakeScrollbarThemePainter::Create(false).PassAs<ScrollbarThemePainter>(), FakeWebScrollbarThemeGeometry::create(), child1->id()); + scoped_refptr<Layer> child2 = ScrollbarLayer::create(scrollbar.Pass(), FakeScrollbarThemePainter::Create(false).PassAs<ScrollbarThemePainter>(), FakeWebScrollbarThemeGeometry::create(true), child1->id()); layerTreeRoot->addChild(child1); layerTreeRoot->insertChild(child2, reverse_order ? 0 : 1); return TreeSynchronizer::synchronizeTrees(layerTreeRoot.get(), scoped_ptr<LayerImpl>(), host_impl->activeTree()).Pass(); @@ -99,7 +99,7 @@ TEST(ScrollbarLayerTest, scrollOffsetSynchronization) scoped_ptr<WebKit::WebScrollbar> scrollbar(FakeWebScrollbar::create()); scoped_refptr<Layer> layerTreeRoot = Layer::create(); scoped_refptr<Layer> contentLayer = Layer::create(); - scoped_refptr<Layer> scrollbarLayer = ScrollbarLayer::create(scrollbar.Pass(), FakeScrollbarThemePainter::Create(false).PassAs<ScrollbarThemePainter>(), FakeWebScrollbarThemeGeometry::create(), layerTreeRoot->id()); + scoped_refptr<Layer> scrollbarLayer = ScrollbarLayer::create(scrollbar.Pass(), FakeScrollbarThemePainter::Create(false).PassAs<ScrollbarThemePainter>(), FakeWebScrollbarThemeGeometry::create(true), layerTreeRoot->id()); layerTreeRoot->addChild(contentLayer); layerTreeRoot->addChild(scrollbarLayer); @@ -147,7 +147,7 @@ public: m_layerTreeHost->initializeRendererIfNeeded(); scoped_ptr<WebKit::WebScrollbar> scrollbar(FakeWebScrollbar::create()); - m_scrollbarLayer = ScrollbarLayer::create(scrollbar.Pass(), FakeScrollbarThemePainter::Create(false).PassAs<ScrollbarThemePainter>(), FakeWebScrollbarThemeGeometry::create(), 1); + m_scrollbarLayer = ScrollbarLayer::create(scrollbar.Pass(), FakeScrollbarThemePainter::Create(false).PassAs<ScrollbarThemePainter>(), FakeWebScrollbarThemeGeometry::create(true), 1); m_scrollbarLayer->setLayerTreeHost(m_layerTreeHost.get()); m_scrollbarLayer->setBounds(m_bounds); m_layerTreeHost->rootLayer()->addChild(m_scrollbarLayer); diff --git a/cc/test/fake_content_layer.cc b/cc/test/fake_content_layer.cc index f217e93..c103b24 100644 --- a/cc/test/fake_content_layer.cc +++ b/cc/test/fake_content_layer.cc @@ -4,6 +4,9 @@ #include "cc/test/fake_content_layer.h" +#include "cc/prioritized_resource.h" +#include "cc/test/fake_content_layer_impl.h" + namespace cc { FakeContentLayer::FakeContentLayer(ContentLayerClient* client) @@ -16,6 +19,11 @@ FakeContentLayer::FakeContentLayer(ContentLayerClient* client) FakeContentLayer::~FakeContentLayer() {} +scoped_ptr<LayerImpl> FakeContentLayer::createLayerImpl( + LayerTreeImpl* tree_impl) { + return FakeContentLayerImpl::Create(tree_impl, m_layerId).PassAs<LayerImpl>(); +} + void FakeContentLayer::update( ResourceUpdateQueue& queue, const OcclusionTracker* occlusion, @@ -24,4 +32,9 @@ void FakeContentLayer::update( update_count_++; } +bool FakeContentLayer::HaveBackingAt(int i, int j) { + const PrioritizedResource* resource = resourceAtForTesting(i, j); + return resource && resource->haveBackingTexture(); +} + } // namespace cc diff --git a/cc/test/fake_content_layer.h b/cc/test/fake_content_layer.h index 7defe6a..94b1266 100644 --- a/cc/test/fake_content_layer.h +++ b/cc/test/fake_content_layer.h @@ -11,12 +11,15 @@ namespace cc { class FakeContentLayer : public ContentLayer { -public: + public: static scoped_refptr<FakeContentLayer> Create(ContentLayerClient* client) { return make_scoped_refptr(new FakeContentLayer(client)); } - int update_count() { return update_count_; } + virtual scoped_ptr<LayerImpl> createLayerImpl(LayerTreeImpl* tree_impl) + OVERRIDE; + + size_t update_count() const { return update_count_; } void reset_update_count() { update_count_ = 0; } virtual void update( @@ -24,11 +27,13 @@ public: const OcclusionTracker* occlusion, RenderingStats& stats) OVERRIDE; -private: + bool HaveBackingAt(int i, int j); + + private: explicit FakeContentLayer(ContentLayerClient* client); virtual ~FakeContentLayer(); - int update_count_; + size_t update_count_; }; } // namespace cc diff --git a/cc/test/fake_content_layer_impl.cc b/cc/test/fake_content_layer_impl.cc new file mode 100644 index 0000000..9404947 --- /dev/null +++ b/cc/test/fake_content_layer_impl.cc @@ -0,0 +1,24 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "cc/test/fake_content_layer_impl.h" + +namespace cc { + +FakeContentLayerImpl::FakeContentLayerImpl(LayerTreeImpl* tree_impl, int id) + : TiledLayerImpl(tree_impl, id), + lost_output_surface_count_(0) { +} + +FakeContentLayerImpl::~FakeContentLayerImpl() {} + +bool FakeContentLayerImpl::HaveResourceForTileAt(int i, int j) { + return hasResourceIdForTileAt(i, j); +} + +void FakeContentLayerImpl::didLoseOutputSurface() { + ++lost_output_surface_count_; +} + +} // namespace cc diff --git a/cc/test/fake_content_layer_impl.h b/cc/test/fake_content_layer_impl.h new file mode 100644 index 0000000..0d797a6 --- /dev/null +++ b/cc/test/fake_content_layer_impl.h @@ -0,0 +1,38 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CC_TEST_FAKE_CONTENT_LAYER_IMPL_H_ +#define CC_TEST_FAKE_CONTENT_LAYER_IMPL_H_ + +#include "base/memory/scoped_ptr.h" +#include "cc/tiled_layer_impl.h" + +namespace cc { + +class FakeContentLayerImpl : public TiledLayerImpl { + public: + static scoped_ptr<FakeContentLayerImpl> Create( + LayerTreeImpl* tree_impl, int id) { + return make_scoped_ptr(new FakeContentLayerImpl(tree_impl, id)); + } + virtual ~FakeContentLayerImpl(); + + bool HaveResourceForTileAt(int i, int j); + + size_t lost_output_surface_count() const { + return lost_output_surface_count_; + } + void reset_lost_output_surface_count() { lost_output_surface_count_ = 0; } + + virtual void didLoseOutputSurface() OVERRIDE; + + private: + explicit FakeContentLayerImpl(LayerTreeImpl* tree_impl, int id); + + size_t lost_output_surface_count_; +}; + +} // namespace cc + +#endif // CC_TEST_FAKE_CONTENT_LAYER_IMPL_H_ diff --git a/cc/test/fake_scrollbar_layer.cc b/cc/test/fake_scrollbar_layer.cc index 7d5d968..d6e5f0a 100644 --- a/cc/test/fake_scrollbar_layer.cc +++ b/cc/test/fake_scrollbar_layer.cc @@ -11,12 +11,12 @@ namespace cc { FakeScrollbarLayer::FakeScrollbarLayer( - bool paint_during_update, int scrolling_layer_id) + bool paint_during_update, bool has_thumb, int scrolling_layer_id) : ScrollbarLayer( FakeWebScrollbar::create().PassAs<WebKit::WebScrollbar>(), FakeScrollbarThemePainter::Create(paint_during_update) .PassAs<ScrollbarThemePainter>(), - FakeWebScrollbarThemeGeometry::create() + FakeWebScrollbarThemeGeometry::create(has_thumb) .PassAs<WebKit::WebScrollbarThemeGeometry>(), scrolling_layer_id), update_count_(0) { diff --git a/cc/test/fake_scrollbar_layer.h b/cc/test/fake_scrollbar_layer.h index 354cf8b..6bc2707 100644 --- a/cc/test/fake_scrollbar_layer.h +++ b/cc/test/fake_scrollbar_layer.h @@ -13,9 +13,9 @@ namespace cc { class FakeScrollbarLayer : public ScrollbarLayer { public: static scoped_refptr<FakeScrollbarLayer> Create( - bool paint_during_update, int scrolling_layer_id) { + bool paint_during_update, bool has_thumb, int scrolling_layer_id) { return make_scoped_refptr(new FakeScrollbarLayer( - paint_during_update, scrolling_layer_id)); + paint_during_update, has_thumb, scrolling_layer_id)); } int update_count() { return update_count_; } @@ -27,7 +27,8 @@ public: RenderingStats& stats) OVERRIDE; private: - FakeScrollbarLayer(bool paint_during_update, int scrolling_layer_id); + FakeScrollbarLayer( + bool paint_during_update, bool has_thumb, int scrolling_layer_id); virtual ~FakeScrollbarLayer(); int update_count_; diff --git a/cc/test/fake_video_frame.cc b/cc/test/fake_video_frame.cc new file mode 100644 index 0000000..3efe462 --- /dev/null +++ b/cc/test/fake_video_frame.cc @@ -0,0 +1,63 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "cc/test/fake_video_frame.h" + +namespace cc { + +FakeVideoFrame::FakeVideoFrame(const scoped_refptr<media::VideoFrame>& frame) + : frame_(frame) {} + +FakeVideoFrame::~FakeVideoFrame() {} + +WebKit::WebVideoFrame::Format FakeVideoFrame::format() const { + return FormatInvalid; +} + +unsigned FakeVideoFrame::width() const { + return frame_->natural_size().width(); +} + +unsigned FakeVideoFrame::height() const { + return frame_->natural_size().height(); +} + +unsigned FakeVideoFrame::planes() const { + return 0; +} + +int FakeVideoFrame::stride(unsigned plane) const { + return 0; +} + +const void* FakeVideoFrame::data(unsigned plane) const { + return NULL; +} + +unsigned FakeVideoFrame::textureId() const { + return frame_->texture_id(); +} + +unsigned FakeVideoFrame::textureTarget() const { + return frame_->texture_target(); +} + +WebKit::WebRect FakeVideoFrame::visibleRect() const { + return frame_->visible_rect(); +} + +WebKit::WebSize FakeVideoFrame::textureSize() const { + return frame_->coded_size(); +} + +// static +media::VideoFrame* FakeVideoFrame::ToVideoFrame( + WebKit::WebVideoFrame* web_video_frame) { + if (!web_video_frame) + return NULL; + FakeVideoFrame* fake_frame = static_cast<FakeVideoFrame*>(web_video_frame); + return fake_frame->frame_.get(); +} + +} // namespace cc diff --git a/cc/test/fake_video_frame.h b/cc/test/fake_video_frame.h new file mode 100644 index 0000000..0631f48 --- /dev/null +++ b/cc/test/fake_video_frame.h @@ -0,0 +1,39 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CC_TEST_FAKE_VIDEO_FRAME_H_ +#define CC_TEST_FAKE_VIDEO_FRAME_H_ + +#include "media/base/video_frame.h" +#include "third_party/WebKit/Source/Platform/chromium/public/WebVideoFrame.h" + +namespace cc { + +class FakeVideoFrame : public WebKit::WebVideoFrame { + public: + explicit FakeVideoFrame(const scoped_refptr<media::VideoFrame>& frame); + virtual ~FakeVideoFrame(); + + // WebKit::WebVideoFrame implementation. + virtual Format format() const; + virtual unsigned width() const; + virtual unsigned height() const; + virtual unsigned planes() const; + virtual int stride(unsigned plane) const; + virtual const void* data(unsigned plane) const; + virtual unsigned textureId() const; + virtual unsigned textureTarget() const; + virtual WebKit::WebRect visibleRect() const; + virtual WebKit::WebSize textureSize() const; + + static media::VideoFrame* ToVideoFrame( + WebKit::WebVideoFrame* web_video_frame); + + private: + scoped_refptr<media::VideoFrame> frame_; +}; + +} // namespace cc + +#endif // CC_TEST_FAKE_VIDEO_FRAME_H_ diff --git a/cc/test/fake_video_frame_provider.cc b/cc/test/fake_video_frame_provider.cc new file mode 100644 index 0000000..bf0a3cf --- /dev/null +++ b/cc/test/fake_video_frame_provider.cc @@ -0,0 +1,25 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "cc/test/fake_video_frame_provider.h" + +namespace cc { + +FakeVideoFrameProvider::FakeVideoFrameProvider() + : frame_(NULL), client_(NULL) {} + +FakeVideoFrameProvider::~FakeVideoFrameProvider() { + if (client_) + client_->stopUsingProvider(); +} + +void FakeVideoFrameProvider::setVideoFrameProviderClient(Client* client) { + client_ = client; +} + +WebKit::WebVideoFrame* FakeVideoFrameProvider::getCurrentFrame() { + return frame_; +} + +} // namespace cc diff --git a/cc/test/fake_video_frame_provider.h b/cc/test/fake_video_frame_provider.h new file mode 100644 index 0000000..f44dee6 --- /dev/null +++ b/cc/test/fake_video_frame_provider.h @@ -0,0 +1,35 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CC_TEST_FAKE_VIDEO_FRAME_PROVIDER_H_ +#define CC_TEST_FAKE_VIDEO_FRAME_PROVIDER_H_ + +#include "base/memory/scoped_ptr.h" +#include "cc/test/fake_video_frame.h" +#include "third_party/WebKit/Source/Platform/chromium/public/WebVideoFrameProvider.h" + +namespace cc { + +// Fake video frame provider that always provides the same VideoFrame. +class FakeVideoFrameProvider: public WebKit::WebVideoFrameProvider { + public: + FakeVideoFrameProvider(); + virtual ~FakeVideoFrameProvider(); + + virtual void setVideoFrameProviderClient(Client* client) OVERRIDE; + virtual WebKit::WebVideoFrame* getCurrentFrame() OVERRIDE; + virtual void putCurrentFrame(WebKit::WebVideoFrame*) OVERRIDE {} + + void set_frame(FakeVideoFrame* frame) { + frame_ = frame; + } + + private: + FakeVideoFrame* frame_; + Client* client_; +}; + +} // namespace cc + +#endif // CC_TEST_FAKE_VIDEO_FRAME_PROVIDER_H_ diff --git a/cc/test/fake_web_graphics_context_3d.cc b/cc/test/fake_web_graphics_context_3d.cc index 5cb39b1..ede316d 100644 --- a/cc/test/fake_web_graphics_context_3d.cc +++ b/cc/test/fake_web_graphics_context_3d.cc @@ -5,8 +5,10 @@ #include "cc/test/fake_web_graphics_context_3d.h" #include <algorithm> +#include <string> #include "base/logging.h" +#include "testing/gtest/include/gtest/gtest.h" #include "third_party/khronos/GLES2/gl2ext.h" using WebKit::WGC3Dboolean; @@ -16,36 +18,69 @@ using WebKit::WebGraphicsContext3D; namespace cc { +static const WebGLId kBufferId = 1; +static const WebGLId kFramebufferId = 2; +static const WebGLId kProgramId = 3; +static const WebGLId kRenderbufferId = 4; +static const WebGLId kShaderId = 5; + +static unsigned s_context_id = 1; + +const WebGLId FakeWebGraphicsContext3D::kExternalTextureId = 1337; + FakeWebGraphicsContext3D::FakeWebGraphicsContext3D() - : next_texture_id_(1) - , context_lost_(false) - , context_lost_callback_(NULL) -{ + : context_id_(s_context_id++), + next_texture_id_(1), + have_extension_io_surface_(false), + have_extension_egl_image_(false), + times_make_current_succeeds_(-1), + times_bind_texture_succeeds_(-1), + times_end_query_succeeds_(-1), + context_lost_(false), + context_lost_callback_(NULL), + width_(0), + height_(0) { } FakeWebGraphicsContext3D::FakeWebGraphicsContext3D( const WebGraphicsContext3D::Attributes& attributes) - : next_texture_id_(1) - , attributes_(attributes) - , context_lost_(false) - , context_lost_callback_(NULL) -{ + : context_id_(s_context_id++), + next_texture_id_(1), + attributes_(attributes), + have_extension_io_surface_(false), + have_extension_egl_image_(false), + times_make_current_succeeds_(-1), + times_bind_texture_succeeds_(-1), + times_end_query_succeeds_(-1), + context_lost_(false), + context_lost_callback_(NULL), + width_(0), + height_(0) { } -FakeWebGraphicsContext3D::~FakeWebGraphicsContext3D() -{ +FakeWebGraphicsContext3D::~FakeWebGraphicsContext3D() { } bool FakeWebGraphicsContext3D::makeContextCurrent() { + if (times_make_current_succeeds_ >= 0) { + if (!times_make_current_succeeds_) + loseContextCHROMIUM(); + --times_make_current_succeeds_; + } return !context_lost_; } int FakeWebGraphicsContext3D::width() { - return 0; + return width_; } int FakeWebGraphicsContext3D::height() { - return 0; + return height_; +} + +void FakeWebGraphicsContext3D::reshape(int width, int height) { + width_ = width; + height_ = height; } bool FakeWebGraphicsContext3D::isGLES2Compliant() { @@ -173,7 +208,16 @@ WebKit::WebString FakeWebGraphicsContext3D::getShaderSource( } WebKit::WebString FakeWebGraphicsContext3D::getString(WGC3Denum name) { - return WebKit::WebString(); + std::string string; + + if (name == GL_EXTENSIONS) { + if (have_extension_io_surface_) + string += "GL_CHROMIUM_iosurface GL_ARB_texture_rectangle "; + if (have_extension_egl_image_) + string += "GL_OES_EGL_image_external"; + } + + return WebKit::WebString::fromUTF8(string.c_str()); } WebKit::WGC3Dint FakeWebGraphicsContext3D::getUniformLocation( @@ -224,39 +268,101 @@ WGC3Dboolean FakeWebGraphicsContext3D::isTexture( } WebGLId FakeWebGraphicsContext3D::createBuffer() { - return 1; + return kBufferId | context_id_ << 16; +} + +void FakeWebGraphicsContext3D::deleteBuffer(WebKit::WebGLId id) { + EXPECT_EQ(kBufferId | context_id_ << 16, id); } WebGLId FakeWebGraphicsContext3D::createFramebuffer() { - return 1; + return kFramebufferId | context_id_ << 16; +} + +void FakeWebGraphicsContext3D::deleteFramebuffer(WebKit::WebGLId id) { + EXPECT_EQ(kFramebufferId | context_id_ << 16, id); } WebGLId FakeWebGraphicsContext3D::createProgram() { - return 1; + return kProgramId | context_id_ << 16; +} + +void FakeWebGraphicsContext3D::deleteProgram(WebKit::WebGLId id) { + EXPECT_EQ(kProgramId | context_id_ << 16, id); } WebGLId FakeWebGraphicsContext3D::createRenderbuffer() { - return 1; + return kRenderbufferId | context_id_ << 16; +} + +void FakeWebGraphicsContext3D::deleteRenderbuffer(WebKit::WebGLId id) { + EXPECT_EQ(kRenderbufferId | context_id_ << 16, id); } WebGLId FakeWebGraphicsContext3D::createShader(WGC3Denum) { - return 1; + return kShaderId | context_id_ << 16; +} + +void FakeWebGraphicsContext3D::deleteShader(WebKit::WebGLId id) { + EXPECT_EQ(kShaderId | context_id_ << 16, id); } WebGLId FakeWebGraphicsContext3D::createTexture() { - WebGLId texture_id = next_texture_id_++; + WebGLId texture_id = NextTextureId(); + DCHECK_NE(texture_id, kExternalTextureId); textures_.push_back(texture_id); return texture_id; } void FakeWebGraphicsContext3D::deleteTexture(WebGLId texture_id) { + DCHECK(std::find(textures_.begin(), textures_.end(), texture_id) != + textures_.end()); textures_.erase(std::find(textures_.begin(), textures_.end(), texture_id)); } +void FakeWebGraphicsContext3D::attachShader(WebGLId program, WebGLId shader) { + EXPECT_EQ(kProgramId | context_id_ << 16, program); + EXPECT_EQ(kShaderId | context_id_ << 16, shader); +} + +void FakeWebGraphicsContext3D::useProgram(WebGLId program) { + if (!program) + return; + EXPECT_EQ(kProgramId | context_id_ << 16, program); +} + +void FakeWebGraphicsContext3D::bindBuffer(WGC3Denum target, WebGLId buffer) { + if (!buffer) + return; + EXPECT_EQ(kBufferId | context_id_ << 16, buffer); +} + +void FakeWebGraphicsContext3D::bindFramebuffer( + WGC3Denum target, WebGLId framebuffer) { + if (!framebuffer) + return; + EXPECT_EQ(kFramebufferId | context_id_ << 16, framebuffer); +} + +void FakeWebGraphicsContext3D::bindRenderbuffer( + WGC3Denum target, WebGLId renderbuffer) { + if (!renderbuffer) + return; + EXPECT_EQ(kRenderbufferId | context_id_ << 16, renderbuffer); +} + void FakeWebGraphicsContext3D::bindTexture( WGC3Denum target, WebGLId texture_id) { + if (times_bind_texture_succeeds_ >= 0) { + if (!times_bind_texture_succeeds_) + loseContextCHROMIUM(); + --times_bind_texture_succeeds_; + } + if (!texture_id) return; + if (texture_id == kExternalTextureId) + return; DCHECK(std::find(textures_.begin(), textures_.end(), texture_id) != textures_.end()); used_textures_.insert(texture_id); @@ -270,15 +376,41 @@ WGC3Dboolean FakeWebGraphicsContext3D::isQueryEXT(WebGLId query) { return true; } -void FakeWebGraphicsContext3D::SetContextLostCallback( +void FakeWebGraphicsContext3D::endQueryEXT(WebKit::WGC3Denum target) { + if (times_end_query_succeeds_ >= 0) { + if (!times_end_query_succeeds_) + loseContextCHROMIUM(); + --times_end_query_succeeds_; + } +} + +void FakeWebGraphicsContext3D::getQueryObjectuivEXT( + WebKit::WebGLId query, + WebKit::WGC3Denum pname, + WebKit::WGC3Duint* params) { + // If the context is lost, behave as if result is available. + if (pname == GL_QUERY_RESULT_AVAILABLE_EXT) + *params = 1; +} + +void FakeWebGraphicsContext3D::setContextLostCallback( WebGraphicsContextLostCallback* callback) { context_lost_callback_ = callback; } void FakeWebGraphicsContext3D::loseContextCHROMIUM() { + if (context_lost_) + return; context_lost_ = true; if (context_lost_callback_) context_lost_callback_->onContextLost(); } +WebKit::WebGLId FakeWebGraphicsContext3D::NextTextureId() { + WebGLId texture_id = next_texture_id_++; + DCHECK(texture_id < (1 << 16)); + texture_id |= context_id_ << 16; + return texture_id; +} + } // namespace cc diff --git a/cc/test/fake_web_graphics_context_3d.h b/cc/test/fake_web_graphics_context_3d.h index f940299..09ec68f 100644 --- a/cc/test/fake_web_graphics_context_3d.h +++ b/cc/test/fake_web_graphics_context_3d.h @@ -33,7 +33,7 @@ class FakeWebGraphicsContext3D : public WebKit::WebGraphicsContext3D { virtual int width(); virtual int height(); - virtual void reshape(int width, int height) {} + virtual void reshape(int width, int height); virtual bool isGLES2Compliant(); @@ -103,16 +103,16 @@ class FakeWebGraphicsContext3D : public WebKit::WebGraphicsContext3D { WebKit::WGC3Dsizei height) {} virtual void activeTexture(WebKit::WGC3Denum texture) {} - virtual void attachShader(WebKit::WebGLId program, WebKit::WebGLId shader) {} + virtual void attachShader(WebKit::WebGLId program, WebKit::WebGLId shader); virtual void bindAttribLocation( WebKit::WebGLId program, WebKit::WGC3Duint index, const WebKit::WGC3Dchar* name) {} - virtual void bindBuffer(WebKit::WGC3Denum target, WebKit::WebGLId buffer) {} + virtual void bindBuffer(WebKit::WGC3Denum target, WebKit::WebGLId buffer); virtual void bindFramebuffer( - WebKit::WGC3Denum target, WebKit::WebGLId framebuffer) {} + WebKit::WGC3Denum target, WebKit::WebGLId framebuffer); virtual void bindRenderbuffer( - WebKit::WGC3Denum target, WebKit::WebGLId renderbuffer) {} + WebKit::WGC3Denum target, WebKit::WebGLId renderbuffer); virtual void bindTexture( WebKit::WGC3Denum target, WebKit::WebGLId texture_id); @@ -504,7 +504,7 @@ class FakeWebGraphicsContext3D : public WebKit::WebGraphicsContext3D { WebKit::WGC3Dboolean transpose, const WebKit::WGC3Dfloat* value) {} - virtual void useProgram(WebKit::WebGLId program) {} + virtual void useProgram(WebKit::WebGLId program); virtual void validateProgram(WebKit::WebGLId program) {} virtual void vertexAttrib1f(WebKit::WGC3Duint index, WebKit::WGC3Dfloat x) {} @@ -556,11 +556,11 @@ class FakeWebGraphicsContext3D : public WebKit::WebGraphicsContext3D { virtual WebKit::WebGLId createShader(WebKit::WGC3Denum); virtual WebKit::WebGLId createTexture(); - virtual void deleteBuffer(WebKit::WebGLId) {} - virtual void deleteFramebuffer(WebKit::WebGLId) {} - virtual void deleteProgram(WebKit::WebGLId) {} - virtual void deleteRenderbuffer(WebKit::WebGLId) {} - virtual void deleteShader(WebKit::WebGLId) {} + virtual void deleteBuffer(WebKit::WebGLId id); + virtual void deleteFramebuffer(WebKit::WebGLId id); + virtual void deleteProgram(WebKit::WebGLId id); + virtual void deleteRenderbuffer(WebKit::WebGLId id); + virtual void deleteShader(WebKit::WebGLId id); virtual void deleteTexture(WebKit::WebGLId texture_id); virtual void texStorage2DEXT( @@ -576,21 +576,32 @@ class FakeWebGraphicsContext3D : public WebKit::WebGraphicsContext3D { virtual void beginQueryEXT( WebKit::WGC3Denum target, WebKit::WebGLId query) {} - virtual void endQueryEXT(WebKit::WGC3Denum target) {} + virtual void endQueryEXT(WebKit::WGC3Denum target); virtual void getQueryivEXT( WebKit::WGC3Denum target, WebKit::WGC3Denum pname, WebKit::WGC3Dint* params) {} virtual void getQueryObjectuivEXT( - WebKit::WebGLId, - WebKit::WGC3Denum, - WebKit::WGC3Duint*) {} + WebKit::WebGLId query, + WebKit::WGC3Denum pname, + WebKit::WGC3Duint* params); - virtual void SetContextLostCallback( + virtual void setContextLostCallback( WebGraphicsContextLostCallback* callback); virtual void loseContextCHROMIUM(); + // When set, MakeCurrent() will fail after this many times. + void set_times_make_current_succeeds(int times) { + times_make_current_succeeds_ = times; + } + void set_times_bind_texture_succeeds(int times) { + times_bind_texture_succeeds_ = times; + } + void set_times_end_query_succeeds(int times) { + times_end_query_succeeds_ = times; + } + size_t NumTextures() const { return textures_.size(); } WebKit::WebGLId TextureAt(int i) const { return textures_[i]; } @@ -600,17 +611,35 @@ class FakeWebGraphicsContext3D : public WebKit::WebGraphicsContext3D { } void ResetUsedTextures() { used_textures_.clear(); } + void set_have_extension_io_surface(bool have) { + have_extension_io_surface_ = have; + } + void set_have_extension_egl_image(bool have) { + have_extension_egl_image_ = have; + } + + static const WebKit::WebGLId kExternalTextureId; + virtual WebKit::WebGLId NextTextureId(); + protected: FakeWebGraphicsContext3D(); FakeWebGraphicsContext3D( const WebKit::WebGraphicsContext3D::Attributes& attributes); + unsigned context_id_; unsigned next_texture_id_; Attributes attributes_; + bool have_extension_io_surface_; + bool have_extension_egl_image_; + int times_make_current_succeeds_; + int times_bind_texture_succeeds_; + int times_end_query_succeeds_; bool context_lost_; WebGraphicsContextLostCallback* context_lost_callback_; std::vector<WebKit::WebGLId> textures_; base::hash_set<WebKit::WebGLId> used_textures_; + int width_; + int height_; }; } // namespace cc diff --git a/cc/test/fake_web_scrollbar_theme_geometry.cc b/cc/test/fake_web_scrollbar_theme_geometry.cc index 7ae7f7a..8a0f378 100644 --- a/cc/test/fake_web_scrollbar_theme_geometry.cc +++ b/cc/test/fake_web_scrollbar_theme_geometry.cc @@ -4,19 +4,25 @@ #include "cc/test/fake_web_scrollbar_theme_geometry.h" +using WebKit::WebRect; + namespace cc { WebKit::WebScrollbarThemeGeometry* FakeWebScrollbarThemeGeometry::clone() const { - return new FakeWebScrollbarThemeGeometry(); + return new FakeWebScrollbarThemeGeometry(m_hasThumb); } int FakeWebScrollbarThemeGeometry::thumbPosition(WebKit::WebScrollbar*) { - return 0; + if (!m_hasThumb) + return 0; + return 5; } int FakeWebScrollbarThemeGeometry::thumbLength(WebKit::WebScrollbar*) { - return 0; + if (!m_hasThumb) + return 0; + return 2; } int FakeWebScrollbarThemeGeometry::trackPosition(WebKit::WebScrollbar*) { @@ -24,7 +30,7 @@ int FakeWebScrollbarThemeGeometry::trackPosition(WebKit::WebScrollbar*) { } int FakeWebScrollbarThemeGeometry::trackLength(WebKit::WebScrollbar*) { - return 0; + return 10; } bool FakeWebScrollbarThemeGeometry::hasButtons(WebKit::WebScrollbar*) { @@ -32,15 +38,17 @@ bool FakeWebScrollbarThemeGeometry::hasButtons(WebKit::WebScrollbar*) { } bool FakeWebScrollbarThemeGeometry::hasThumb(WebKit::WebScrollbar*) { - return false; + return m_hasThumb; } -WebKit::WebRect FakeWebScrollbarThemeGeometry::trackRect(WebKit::WebScrollbar*) { - return WebKit::WebRect(); +WebRect FakeWebScrollbarThemeGeometry::trackRect(WebKit::WebScrollbar*) { + return WebRect(0, 0, 10, 10); } -WebKit::WebRect FakeWebScrollbarThemeGeometry::thumbRect(WebKit::WebScrollbar*) { - return WebKit::WebRect(); +WebRect FakeWebScrollbarThemeGeometry::thumbRect(WebKit::WebScrollbar*) { + if (!m_hasThumb) + return WebRect(0, 0, 0, 0); + return WebRect(0, 5, 5, 2); } int FakeWebScrollbarThemeGeometry::minimumThumbLength(WebKit::WebScrollbar*) { @@ -51,41 +59,47 @@ int FakeWebScrollbarThemeGeometry::scrollbarThickness(WebKit::WebScrollbar*) { return 0; } -WebKit::WebRect FakeWebScrollbarThemeGeometry::backButtonStartRect( +WebRect FakeWebScrollbarThemeGeometry::backButtonStartRect( WebKit::WebScrollbar*) { - return WebKit::WebRect(); + return WebRect(); } -WebKit::WebRect FakeWebScrollbarThemeGeometry::backButtonEndRect( +WebRect FakeWebScrollbarThemeGeometry::backButtonEndRect( WebKit::WebScrollbar*) { - return WebKit::WebRect(); + return WebRect(); } -WebKit::WebRect FakeWebScrollbarThemeGeometry::forwardButtonStartRect( +WebRect FakeWebScrollbarThemeGeometry::forwardButtonStartRect( WebKit::WebScrollbar*) { - return WebKit::WebRect(); + return WebRect(); } -WebKit::WebRect FakeWebScrollbarThemeGeometry::forwardButtonEndRect( +WebRect FakeWebScrollbarThemeGeometry::forwardButtonEndRect( WebKit::WebScrollbar*) { - return WebKit::WebRect(); + return WebRect(); } -WebKit::WebRect FakeWebScrollbarThemeGeometry::constrainTrackRectToTrackPieces( +WebRect FakeWebScrollbarThemeGeometry::constrainTrackRectToTrackPieces( WebKit::WebScrollbar*, - const WebKit::WebRect&) { - return WebKit::WebRect(); + const WebRect&) { + return WebRect(); } void FakeWebScrollbarThemeGeometry::splitTrack( WebKit::WebScrollbar*, - const WebKit::WebRect& track, - WebKit::WebRect& startTrack, - WebKit::WebRect& thumb, - WebKit::WebRect& endTrack) { - startTrack = WebKit::WebRect(); - thumb = WebKit::WebRect(); - endTrack = WebKit::WebRect(); + const WebRect& track, + WebRect& startTrack, + WebRect& thumb, + WebRect& endTrack) { + if (!m_hasThumb) { + thumb = WebRect(0, 0, 0, 0); + startTrack = WebRect(0, 0, 10, 10); + endTrack = WebRect(0, 10, 10, 0); + } else { + thumb = WebRect(0, 5, 5, 2); + startTrack = WebRect(0, 5, 0, 5); + endTrack = WebRect(0, 0, 0, 5); + } } } // namespace cc diff --git a/cc/test/fake_web_scrollbar_theme_geometry.h b/cc/test/fake_web_scrollbar_theme_geometry.h index 45bd1b7..6c3d38c 100644 --- a/cc/test/fake_web_scrollbar_theme_geometry.h +++ b/cc/test/fake_web_scrollbar_theme_geometry.h @@ -12,7 +12,7 @@ namespace cc { class FakeWebScrollbarThemeGeometry : public WebKit::WebScrollbarThemeGeometry { public: - static scoped_ptr<WebKit::WebScrollbarThemeGeometry> create() { return scoped_ptr<WebKit::WebScrollbarThemeGeometry>(new FakeWebScrollbarThemeGeometry()); } + static scoped_ptr<WebKit::WebScrollbarThemeGeometry> create(bool hasThumb) { return scoped_ptr<WebKit::WebScrollbarThemeGeometry>(new FakeWebScrollbarThemeGeometry(hasThumb)); } virtual WebKit::WebScrollbarThemeGeometry* clone() const OVERRIDE; @@ -32,6 +32,10 @@ public: virtual WebKit::WebRect forwardButtonEndRect(WebKit::WebScrollbar*) OVERRIDE; virtual WebKit::WebRect constrainTrackRectToTrackPieces(WebKit::WebScrollbar*, const WebKit::WebRect&) OVERRIDE; virtual void splitTrack(WebKit::WebScrollbar*, const WebKit::WebRect& track, WebKit::WebRect& startTrack, WebKit::WebRect& thumb, WebKit::WebRect& endTrack) OVERRIDE; + +protected: + FakeWebScrollbarThemeGeometry(bool hasThumb) : m_hasThumb(hasThumb) { } + bool m_hasThumb; }; } // namespace cc diff --git a/cc/test/layer_tree_test_common.h b/cc/test/layer_tree_test_common.h index 05e37fe..3b0cfd6 100644 --- a/cc/test/layer_tree_test_common.h +++ b/cc/test/layer_tree_test_common.h @@ -176,44 +176,4 @@ private: SINGLE_THREAD_TEST_F(TEST_FIXTURE_NAME) \ MULTI_THREAD_TEST_F(TEST_FIXTURE_NAME) -#define MULTI_THREAD_TEST_P1(TEST_FIXTURE_NAME, P1_NAME, P1) \ - class TEST_FIXTURE_NAME##_##P1_NAME : public TEST_FIXTURE_NAME { \ - public: \ - TEST_FIXTURE_NAME##_##P1_NAME() \ - : TEST_FIXTURE_NAME(P1) {} \ - }; \ - MULTI_THREAD_TEST_F(TEST_FIXTURE_NAME##_##P1) - -#define SINGLE_THREAD_TEST_P1(TEST_FIXTURE_NAME, P1_NAME, P1) \ - class TEST_FIXTURE_NAME##_##P1_NAME : public TEST_FIXTURE_NAME { \ - public: \ - TEST_FIXTURE_NAME##_##P1_NAME() \ - : TEST_FIXTURE_NAME(P1) {} \ - }; \ - SINGLE_THREAD_TEST_F(TEST_FIXTURE_NAME##_##P1_NAME) - -#define SINGLE_AND_MULTI_THREAD_TEST_P1(TEST_FIXTURE_NAME, P1_NAME, P1) \ - SINGLE_THREAD_TEST_P1(TEST_FIXTURE_NAME, P1) \ - MULTI_THREAD_TEST_P1(TEST_FIXTURE_NAME, P1) - -#define MULTI_THREAD_TEST_P2(TEST_FIXTURE_NAME, P1_NAME, P1, P2_NAME, P2) \ - class TEST_FIXTURE_NAME##_##P1_NAME##_##P2_NAME : public TEST_FIXTURE_NAME { \ - public: \ - TEST_FIXTURE_NAME##_##P1_NAME##_##P2_NAME() \ - : TEST_FIXTURE_NAME(P1, P2) {} \ - }; \ - MULTI_THREAD_TEST_F(TEST_FIXTURE_NAME##_##P1_NAME##_##P2_NAME) - -#define SINGLE_THREAD_TEST_P2(TEST_FIXTURE_NAME, P1_NAME, P1, P2_NAME, P2) \ - class TEST_FIXTURE_NAME##_##P1_NAME##_##P2_NAME : public TEST_FIXTURE_NAME { \ - public: \ - TEST_FIXTURE_NAME##_##P1_NAME##_##P2_NAME() \ - : TEST_FIXTURE_NAME(P1, P2) {} \ - }; \ - SINGLE_THREAD_TEST_F(TEST_FIXTURE_NAME##_##P1_NAME##_##P2_NAME) - -#define SINGLE_AND_MULTI_THREAD_TEST_P2(TEST_FIXTURE_NAME, P1_NAME, P1, P2_NAME, P2) \ - SINGLE_THREAD_TEST_P1(TEST_FIXTURE_NAME, P1, P2) \ - MULTI_THREAD_TEST_P1(TEST_FIXTURE_NAME, P1, P2) - #endif // CC_TEST_LAYER_TREE_TEST_COMMON_H_ diff --git a/cc/test/render_pass_test_common.cc b/cc/test/render_pass_test_common.cc index 5f901f2..b66ca4f 100644 --- a/cc/test/render_pass_test_common.cc +++ b/cc/test/render_pass_test_common.cc @@ -29,6 +29,9 @@ void TestRenderPass::AppendOneOfEveryQuadType( gfx::Size(20, 12), resourceProvider->bestTextureFormat(), ResourceProvider::TextureUsageAny); + unsigned texture_id = ResourceProvider::ScopedReadLockGL( + resourceProvider, texture_resource).textureId(); + scoped_ptr<cc::SharedQuadState> shared_state = cc::SharedQuadState::Create(); shared_state->SetAll(gfx::Transform(), rect, @@ -58,7 +61,7 @@ void TestRenderPass::AppendOneOfEveryQuadType( rect, opaque_rect, gfx::Size(50, 50), - 1, + texture_id, cc::IOSurfaceDrawQuad::FLIPPED); AppendQuad(io_surface_quad.PassAs<DrawQuad>()); @@ -88,7 +91,7 @@ void TestRenderPass::AppendOneOfEveryQuadType( stream_video_quad->SetNew(shared_state.get(), rect, opaque_rect, - 1, + texture_id, gfx::Transform()); AppendQuad(stream_video_quad.PassAs<DrawQuad>()); @@ -156,7 +159,10 @@ void TestRenderPass::AppendOneOfEveryQuadType( cc::VideoLayerImpl::FramePlane planes[3]; for (int i = 0; i < 3; ++i) { planes[i].resourceId = - resourceProvider->createResourceFromExternalTexture(1); + resourceProvider->createResource( + gfx::Size(20, 12), + resourceProvider->bestTextureFormat(), + ResourceProvider::TextureUsageAny); planes[i].size = gfx::Size(100, 100); planes[i].format = GL_LUMINANCE; } diff --git a/cc/tiled_layer.cc b/cc/tiled_layer.cc index a390267..d93f65d 100644 --- a/cc/tiled_layer.cc +++ b/cc/tiled_layer.cc @@ -230,6 +230,14 @@ PrioritizedResourceManager* TiledLayer::resourceManager() const return layerTreeHost()->contentsTextureManager(); } +const PrioritizedResource* TiledLayer::resourceAtForTesting(int i, int j) const +{ + UpdatableTile* tile = tileAt(i, j); + if (!tile) + return 0; + return tile->managedResource(); +} + void TiledLayer::setLayerTreeHost(LayerTreeHost* host) { if (host && host != layerTreeHost()) { diff --git a/cc/tiled_layer.h b/cc/tiled_layer.h index 9d47784..e09780c 100644 --- a/cc/tiled_layer.h +++ b/cc/tiled_layer.h @@ -65,6 +65,8 @@ protected: // Virtual for testing virtual PrioritizedResourceManager* resourceManager() const; + const LayerTilingData* tilerForTesting() const { return m_tiler.get(); } + const PrioritizedResource* resourceAtForTesting(int, int) const; private: virtual scoped_ptr<LayerImpl> createLayerImpl(LayerTreeImpl* treeImpl) OVERRIDE; |