1 // Copyright 2013 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "base/command_line.h" 6 #include "base/run_loop.h" 7 #include "content/browser/gpu/browser_gpu_channel_host_factory.h" 8 #include "content/browser/gpu/gpu_process_host_ui_shim.h" 9 #include "content/common/gpu/client/context_provider_command_buffer.h" 10 #include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h" 11 #include "content/common/gpu/gpu_process_launch_causes.h" 12 #include "content/public/browser/browser_thread.h" 13 #include "content/public/browser/gpu_data_manager.h" 14 #include "content/public/common/content_switches.h" 15 #include "content/test/content_browser_test.h" 16 #include "ui/gl/gl_switches.h" 17 #include "webkit/common/gpu/webgraphicscontext3d_in_process_command_buffer_impl.h" 18 19 namespace { 20 21 using content::WebGraphicsContext3DCommandBufferImpl; 22 23 class ContextTestBase : public content::ContentBrowserTest { 24 public: 25 virtual void SetUpOnMainThread() OVERRIDE { 26 if (!content::BrowserGpuChannelHostFactory::CanUseForTesting()) 27 return; 28 29 if (!content::BrowserGpuChannelHostFactory::instance()) 30 content::BrowserGpuChannelHostFactory::Initialize(true); 31 32 content::BrowserGpuChannelHostFactory* factory = 33 content::BrowserGpuChannelHostFactory::instance(); 34 CHECK(factory); 35 scoped_refptr<content::GpuChannelHost> gpu_channel_host( 36 factory->EstablishGpuChannelSync( 37 content:: 38 CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE)); 39 context_.reset( 40 WebGraphicsContext3DCommandBufferImpl::CreateOffscreenContext( 41 gpu_channel_host.get(), 42 blink::WebGraphicsContext3D::Attributes(), 43 GURL(), 44 WebGraphicsContext3DCommandBufferImpl::SharedMemoryLimits())); 45 CHECK(context_.get()); 46 context_->makeContextCurrent(); 47 context_support_ = context_->GetContextSupport(); 48 ContentBrowserTest::SetUpOnMainThread(); 49 } 50 51 virtual void TearDownOnMainThread() OVERRIDE { 52 // Must delete the context first. 53 context_.reset(NULL); 54 ContentBrowserTest::TearDownOnMainThread(); 55 } 56 57 protected: 58 scoped_ptr<WebGraphicsContext3DCommandBufferImpl> context_; 59 gpu::ContextSupport* context_support_; 60 }; 61 62 } // namespace 63 64 // Include the shared tests. 65 #define CONTEXT_TEST_F IN_PROC_BROWSER_TEST_F 66 #include "content/common/gpu/client/gpu_context_tests.h" 67 68 namespace content { 69 70 class BrowserGpuChannelHostFactoryTest : public ContextTestBase { 71 public: 72 virtual void SetUpOnMainThread() OVERRIDE { 73 if (!content::BrowserGpuChannelHostFactory::CanUseForTesting()) 74 return; 75 76 // Start all tests without a gpu channel so that the tests exercise a 77 // consistent codepath. 78 if (!content::BrowserGpuChannelHostFactory::instance()) 79 content::BrowserGpuChannelHostFactory::Initialize(false); 80 81 CHECK(GetFactory()); 82 83 ContentBrowserTest::SetUpOnMainThread(); 84 } 85 86 virtual void TearDownOnMainThread() OVERRIDE { 87 ContextTestBase::TearDownOnMainThread(); 88 } 89 90 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { 91 // Start all tests without a gpu channel so that the tests exercise a 92 // consistent codepath. 93 command_line->AppendSwitch(switches::kDisableGpuProcessPrelaunch); 94 } 95 96 void OnContextLost(const base::Closure callback, int* counter) { 97 (*counter)++; 98 callback.Run(); 99 } 100 101 protected: 102 BrowserGpuChannelHostFactory* GetFactory() { 103 return BrowserGpuChannelHostFactory::instance(); 104 } 105 106 bool IsChannelEstablished() { 107 return GetFactory()->GetGpuChannel() != NULL; 108 } 109 110 void EstablishAndWait() { 111 base::RunLoop run_loop; 112 GetFactory()->EstablishGpuChannel( 113 CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE, 114 run_loop.QuitClosure()); 115 run_loop.Run(); 116 } 117 118 GpuChannelHost* GetGpuChannel() { 119 return GetFactory()->GetGpuChannel(); 120 } 121 122 static void Signal(bool *event) { 123 CHECK_EQ(*event, false); 124 *event = true; 125 } 126 127 scoped_ptr<WebGraphicsContext3DCommandBufferImpl> CreateContext() { 128 return make_scoped_ptr( 129 WebGraphicsContext3DCommandBufferImpl::CreateOffscreenContext( 130 GetGpuChannel(), 131 blink::WebGraphicsContext3D::Attributes(), 132 GURL(), 133 WebGraphicsContext3DCommandBufferImpl::SharedMemoryLimits())); 134 } 135 }; 136 137 IN_PROC_BROWSER_TEST_F(BrowserGpuChannelHostFactoryTest, Basic) { 138 if (!context_) 139 return; 140 141 DCHECK(!IsChannelEstablished()); 142 EstablishAndWait(); 143 EXPECT_TRUE(GetGpuChannel() != NULL); 144 } 145 146 IN_PROC_BROWSER_TEST_F(BrowserGpuChannelHostFactoryTest, 147 EstablishAndTerminate) { 148 if (!context_) 149 return; 150 151 DCHECK(!IsChannelEstablished()); 152 base::RunLoop run_loop; 153 GetFactory()->EstablishGpuChannel( 154 CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE, 155 run_loop.QuitClosure()); 156 GetFactory()->Terminate(); 157 158 // The callback should still trigger. 159 run_loop.Run(); 160 } 161 162 IN_PROC_BROWSER_TEST_F(BrowserGpuChannelHostFactoryTest, AlreadyEstablished) { 163 if (!context_) 164 return; 165 166 DCHECK(!IsChannelEstablished()); 167 scoped_refptr<GpuChannelHost> gpu_channel = 168 GetFactory()->EstablishGpuChannelSync( 169 CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE); 170 171 // Expect established callback immediately. 172 bool event = false; 173 GetFactory()->EstablishGpuChannel( 174 CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE, 175 base::Bind(&BrowserGpuChannelHostFactoryTest::Signal, &event)); 176 EXPECT_TRUE(event); 177 EXPECT_EQ(gpu_channel, GetGpuChannel()); 178 } 179 180 IN_PROC_BROWSER_TEST_F(BrowserGpuChannelHostFactoryTest, CrashAndRecover) { 181 if (!context_) 182 return; 183 184 DCHECK(!IsChannelEstablished()); 185 EstablishAndWait(); 186 scoped_refptr<GpuChannelHost> host = GetGpuChannel(); 187 188 scoped_refptr<ContextProviderCommandBuffer> provider = 189 ContextProviderCommandBuffer::Create(CreateContext(), 190 "BrowserGpuChannelHostFactoryTest"); 191 base::RunLoop run_loop; 192 int counter = 0; 193 provider->SetLostContextCallback( 194 base::Bind(&BrowserGpuChannelHostFactoryTest::OnContextLost, 195 base::Unretained(this), run_loop.QuitClosure(), &counter)); 196 EXPECT_TRUE(provider->BindToCurrentThread()); 197 GpuProcessHostUIShim* shim = 198 GpuProcessHostUIShim::FromID(GetFactory()->GpuProcessHostId()); 199 EXPECT_TRUE(shim != NULL); 200 shim->SimulateCrash(); 201 run_loop.Run(); 202 203 EXPECT_EQ(1, counter); 204 EXPECT_FALSE(IsChannelEstablished()); 205 EstablishAndWait(); 206 EXPECT_TRUE(IsChannelEstablished()); 207 } 208 209 } // namespace content 210