Home | History | Annotate | Download | only in gpu
      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