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