diff options
Diffstat (limited to 'content')
15 files changed, 542 insertions, 297 deletions
diff --git a/content/browser/aura/gpu_process_transport_factory.cc b/content/browser/aura/gpu_process_transport_factory.cc index 2d09b24..6e2acfc 100644 --- a/content/browser/aura/gpu_process_transport_factory.cc +++ b/content/browser/aura/gpu_process_transport_factory.cc @@ -221,12 +221,15 @@ scoped_ptr<cc::OutputSurface> GpuProcessTransportFactory::CreateOutputSurface( data = CreatePerCompositorData(compositor); scoped_refptr<ContextProviderCommandBuffer> context_provider; + base::WeakPtr<WebGraphicsContext3DSwapBuffersClient> swap_client_weak_ptr; + if (data->swap_client) + swap_client_weak_ptr = data->swap_client->AsWeakPtr(); CommandLine* command_line = CommandLine::ForCurrentProcess(); if (!command_line->HasSwitch(switches::kUIEnableSoftwareCompositing)) { context_provider = ContextProviderCommandBuffer::Create( GpuProcessTransportFactory::CreateContextCommon( - data->swap_client->AsWeakPtr(), + swap_client_weak_ptr, data->surface_id), "Compositor"); } @@ -448,7 +451,8 @@ void GpuProcessTransportFactory::OnLostContext(ui::Compositor* compositor) { // Prevent callbacks from other contexts in the same share group from // calling us again. - data->swap_client.reset(new CompositorSwapClient(compositor, this)); + if (data->swap_client.get()) + data->swap_client.reset(new CompositorSwapClient(compositor, this)); compositor->OnSwapBuffersAborted(); } @@ -462,7 +466,8 @@ GpuProcessTransportFactory::CreatePerCompositorData( PerCompositorData* data = new PerCompositorData; data->surface_id = tracker->AddSurfaceForNativeWidget(widget); - data->swap_client.reset(new CompositorSwapClient(compositor, this)); + if (!ui::Compositor::WasInitializedWithThread()) + data->swap_client.reset(new CompositorSwapClient(compositor, this)); #if defined(OS_WIN) if (GpuDataManagerImpl::GetInstance()->IsUsingAcceleratedSurface()) data->accelerated_surface.reset(new AcceleratedSurface(widget)); @@ -488,19 +493,21 @@ GpuProcessTransportFactory::CreateContextCommon( attrs.stencil = false; attrs.antialias = false; attrs.noAutomaticFlushes = true; - GpuChannelHostFactory* factory = BrowserGpuChannelHostFactory::instance(); + scoped_refptr<GpuChannelHost> gpu_channel_host( + BrowserGpuChannelHostFactory::instance()->EstablishGpuChannelSync( + CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE)); + if (!gpu_channel_host) + return scoped_ptr<WebGraphicsContext3DCommandBufferImpl>(); GURL url("chrome://gpu/GpuProcessTransportFactory::CreateContextCommon"); scoped_ptr<WebGraphicsContext3DCommandBufferImpl> context( new WebGraphicsContext3DCommandBufferImpl( surface_id, url, - factory, - swap_client)); - if (!context->InitializeWithDefaultBufferSizes( - attrs, - false, - CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE)) - return scoped_ptr<WebGraphicsContext3DCommandBufferImpl>(); + gpu_channel_host.get(), + swap_client, + attrs, + false, + WebGraphicsContext3DCommandBufferImpl::SharedMemoryLimits())); return context.Pass(); } diff --git a/content/browser/browser_main_loop.cc b/content/browser/browser_main_loop.cc index f8c8a1c..adccbd4 100644 --- a/content/browser/browser_main_loop.cc +++ b/content/browser/browser_main_loop.cc @@ -853,7 +853,8 @@ void BrowserMainLoop::ShutdownThreadsAndCleanUp() { // it. { TRACE_EVENT0("shutdown", "BrowserMainLoop::Subsystem:GPUChannelFactory"); - BrowserGpuChannelHostFactory::Terminate(); + if (BrowserGpuChannelHostFactory::instance()) + BrowserGpuChannelHostFactory::Terminate(); } // Must happen after the I/O thread is shutdown since this class lives on the @@ -910,9 +911,26 @@ int BrowserMainLoop::BrowserThreadsStarted() { #if !defined(OS_IOS) HistogramSynchronizer::GetInstance(); - BrowserGpuChannelHostFactory::Initialize(); + // Initialize the GpuDataManager before we set up the MessageLoops because + // otherwise we'll trigger the assertion about doing IO on the UI thread. + GpuDataManagerImpl::GetInstance()->Initialize(); + + bool always_uses_gpu = IsForceCompositingModeEnabled(); + bool established_gpu_channel = false; +#if defined(USE_AURA) || defined(OS_ANDROID) + established_gpu_channel = + !parsed_command_line_.HasSwitch(switches::kDisableGpuProcessPrelaunch) || + parsed_command_line_.HasSwitch(switches::kSingleProcess) || + parsed_command_line_.HasSwitch(switches::kInProcessGPU); #if defined(USE_AURA) + if (GpuDataManagerImpl::GetInstance()->CanUseGpuBrowserCompositor()) + BrowserGpuChannelHostFactory::Initialize(established_gpu_channel); + else + always_uses_gpu = false; ImageTransportFactory::Initialize(); +#elif defined(OS_ANDROID) + BrowserGpuChannelHostFactory::Initialize(established_gpu_channel); +#endif #endif #if defined(OS_LINUX) @@ -935,10 +953,6 @@ int BrowserMainLoop::BrowserThreadsStarted() { media_stream_manager_.reset(new MediaStreamManager(audio_manager_.get())); } - // Initialize the GpuDataManager before we set up the MessageLoops because - // otherwise we'll trigger the assertion about doing IO on the UI thread. - GpuDataManagerImpl::GetInstance()->Initialize(); - { TRACE_EVENT0("startup", "BrowserMainLoop::BrowserThreadsStarted:InitSpeechRecognition"); @@ -969,12 +983,8 @@ int BrowserMainLoop::BrowserThreadsStarted() { // When running the GPU thread in-process, avoid optimistically starting it // since creating the GPU thread races against creation of the one-and-only // ChildProcess instance which is created by the renderer thread. - bool always_uses_gpu = IsForceCompositingModeEnabled(); -#if defined(USE_AURA) - if (!GpuDataManagerImpl::GetInstance()->CanUseGpuBrowserCompositor()) - always_uses_gpu = false; -#endif if (GpuDataManagerImpl::GetInstance()->GpuAccessAllowed(NULL) && + !established_gpu_channel && always_uses_gpu && !parsed_command_line_.HasSwitch(switches::kDisableGpuProcessPrelaunch) && !parsed_command_line_.HasSwitch(switches::kSingleProcess) && diff --git a/content/browser/gpu/browser_gpu_channel_host_factory.cc b/content/browser/gpu/browser_gpu_channel_host_factory.cc index 7bc6fca..8de6d11 100644 --- a/content/browser/gpu/browser_gpu_channel_host_factory.cc +++ b/content/browser/gpu/browser_gpu_channel_host_factory.cc @@ -5,6 +5,7 @@ #include "content/browser/gpu/browser_gpu_channel_host_factory.h" #include "base/bind.h" +#include "base/debug/trace_event.h" #include "base/threading/thread_restrictions.h" #include "content/browser/gpu/gpu_data_manager_impl.h" #include "content/browser/gpu/gpu_process_host.h" @@ -20,7 +21,7 @@ namespace content { BrowserGpuChannelHostFactory* BrowserGpuChannelHostFactory::instance_ = NULL; BrowserGpuChannelHostFactory::CreateRequest::CreateRequest() - : event(false, false), + : event(true, false), gpu_host_id(0), route_id(MSG_ROUTING_NONE) { } @@ -29,32 +30,137 @@ BrowserGpuChannelHostFactory::CreateRequest::~CreateRequest() { } BrowserGpuChannelHostFactory::EstablishRequest::EstablishRequest( - CauseForGpuLaunch cause) - : event(false, false), - cause_for_gpu_launch(cause), - gpu_host_id(0), - reused_gpu_process(true) { + CauseForGpuLaunch cause, + int gpu_client_id, + int gpu_host_id) + : event_(false, false), + cause_for_gpu_launch_(cause), + gpu_client_id_(gpu_client_id), + gpu_host_id_(gpu_host_id), + reused_gpu_process_(false), + finished_(false), + main_loop_(base::MessageLoopProxy::current()) { + scoped_refptr<base::MessageLoopProxy> loop = + BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO); + loop->PostTask( + FROM_HERE, + base::Bind(&BrowserGpuChannelHostFactory::EstablishRequest::EstablishOnIO, + this)); } BrowserGpuChannelHostFactory::EstablishRequest::~EstablishRequest() { } -void BrowserGpuChannelHostFactory::Initialize() { - instance_ = new BrowserGpuChannelHostFactory(); +void BrowserGpuChannelHostFactory::EstablishRequest::EstablishOnIO() { + GpuProcessHost* host = GpuProcessHost::FromID(gpu_host_id_); + if (!host) { + host = GpuProcessHost::Get(GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED, + cause_for_gpu_launch_); + if (!host) { + FinishOnIO(); + return; + } + gpu_host_id_ = host->host_id(); + reused_gpu_process_ = false; + } else { + if (reused_gpu_process_) { + // We come here if we retried to establish the channel because of a + // failure in ChannelEstablishedOnIO, but we ended up with the same + // process ID, meaning the failure was not because of a channel error, + // but another reason. So fail now. + FinishOnIO(); + return; + } + reused_gpu_process_ = true; + } + + host->EstablishGpuChannel( + gpu_client_id_, + true, + base::Bind( + &BrowserGpuChannelHostFactory::EstablishRequest::OnEstablishedOnIO, + this)); +} + +void BrowserGpuChannelHostFactory::EstablishRequest::OnEstablishedOnIO( + const IPC::ChannelHandle& channel_handle, + const gpu::GPUInfo& gpu_info) { + if (channel_handle.name.empty() && reused_gpu_process_) { + // We failed after re-using the GPU process, but it may have died in the + // mean time. Retry to have a chance to create a fresh GPU process. + EstablishOnIO(); + } else { + channel_handle_ = channel_handle; + gpu_info_ = gpu_info; + FinishOnIO(); + } +} + +void BrowserGpuChannelHostFactory::EstablishRequest::FinishOnIO() { + event_.Signal(); + main_loop_->PostTask( + FROM_HERE, + base::Bind(&BrowserGpuChannelHostFactory::EstablishRequest::FinishOnMain, + this)); +} + +void BrowserGpuChannelHostFactory::EstablishRequest::FinishOnMain() { + if (!finished_) { + BrowserGpuChannelHostFactory* factory = + BrowserGpuChannelHostFactory::instance(); + factory->GpuChannelEstablished(); + finished_ = true; + } +} + +void BrowserGpuChannelHostFactory::EstablishRequest::Wait() { + DCHECK(main_loop_->BelongsToCurrentThread()); + { + // We're blocking the UI thread, which is generally undesirable. + // In this case we need to wait for this before we can show any UI + // /anyway/, so it won't cause additional jank. + // TODO(piman): Make this asynchronous (http://crbug.com/125248). + TRACE_EVENT0("browser", + "BrowserGpuChannelHostFactory::EstablishGpuChannelSync"); + base::ThreadRestrictions::ScopedAllowWait allow_wait; + event_.Wait(); + } + FinishOnMain(); +} + +void BrowserGpuChannelHostFactory::EstablishRequest::Cancel() { + DCHECK(main_loop_->BelongsToCurrentThread()); + finished_ = true; +} + +void BrowserGpuChannelHostFactory::Initialize(bool establish_gpu_channel) { + DCHECK(!instance_); + instance_ = new BrowserGpuChannelHostFactory(establish_gpu_channel); } void BrowserGpuChannelHostFactory::Terminate() { + DCHECK(instance_); delete instance_; instance_ = NULL; } -BrowserGpuChannelHostFactory::BrowserGpuChannelHostFactory() +BrowserGpuChannelHostFactory::BrowserGpuChannelHostFactory( + bool establish_gpu_channel) : gpu_client_id_(ChildProcessHostImpl::GenerateChildProcessUniqueId()), shutdown_event_(new base::WaitableEvent(true, false)), gpu_host_id_(0) { + if (establish_gpu_channel) { + pending_request_ = new EstablishRequest( + CAUSE_FOR_GPU_LAUNCH_BROWSER_STARTUP, gpu_client_id_, gpu_host_id_); + } } BrowserGpuChannelHostFactory::~BrowserGpuChannelHostFactory() { + DCHECK(IsMainThread()); + if (pending_request_) + pending_request_->Cancel(); + for (size_t n = 0; n < established_callbacks_.size(); n++) + established_callbacks_[n].Run(); shutdown_event_->Signal(); } @@ -126,6 +232,8 @@ int32 BrowserGpuChannelHostFactory::CreateViewCommandBuffer( // In this case we need to wait for this before we can show any UI /anyway/, // so it won't cause additional jank. // TODO(piman): Make this asynchronous (http://crbug.com/125248). + TRACE_EVENT0("browser", + "BrowserGpuChannelHostFactory::CreateViewCommandBuffer"); base::ThreadRestrictions::ScopedAllowWait allow_wait; request.event.Wait(); return request.route_id; @@ -197,91 +305,65 @@ void BrowserGpuChannelHostFactory::DeleteImage( sync_point)); } -void BrowserGpuChannelHostFactory::EstablishGpuChannelOnIO( - EstablishRequest* request) { - GpuProcessHost* host = GpuProcessHost::FromID(gpu_host_id_); - if (!host) { - host = GpuProcessHost::Get(GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED, - request->cause_for_gpu_launch); - if (!host) { - request->event.Signal(); - return; - } - gpu_host_id_ = host->host_id(); - request->reused_gpu_process = false; - } else { - if (host->host_id() == request->gpu_host_id) { - // We come here if we retried to establish the channel because of a - // failure in GpuChannelEstablishedOnIO, but we ended up with the same - // process ID, meaning the failure was not because of a channel error, but - // another reason. So fail now. - request->event.Signal(); - return; - } - request->reused_gpu_process = true; - } - request->gpu_host_id = gpu_host_id_; +GpuChannelHost* BrowserGpuChannelHostFactory::EstablishGpuChannelSync( + CauseForGpuLaunch cause_for_gpu_launch) { + EstablishGpuChannel(cause_for_gpu_launch, base::Closure()); - host->EstablishGpuChannel( - gpu_client_id_, - true, - base::Bind(&BrowserGpuChannelHostFactory::GpuChannelEstablishedOnIO, - base::Unretained(this), - request)); -} + if (pending_request_) + pending_request_->Wait(); -void BrowserGpuChannelHostFactory::GpuChannelEstablishedOnIO( - EstablishRequest* request, - const IPC::ChannelHandle& channel_handle, - const gpu::GPUInfo& gpu_info) { - if (channel_handle.name.empty() && request->reused_gpu_process) { - // We failed after re-using the GPU process, but it may have died in the - // mean time. Retry to have a chance to create a fresh GPU process. - EstablishGpuChannelOnIO(request); - } else { - request->channel_handle = channel_handle; - request->gpu_info = gpu_info; - request->event.Signal(); - } + return gpu_channel_.get(); } -GpuChannelHost* BrowserGpuChannelHostFactory::EstablishGpuChannelSync( - CauseForGpuLaunch cause_for_gpu_launch) { - if (gpu_channel_.get()) { +void BrowserGpuChannelHostFactory::EstablishGpuChannel( + CauseForGpuLaunch cause_for_gpu_launch, + const base::Closure& callback) { + if (gpu_channel_.get() && gpu_channel_->IsLost()) { + DCHECK(!pending_request_); // Recreate the channel if it has been lost. - if (gpu_channel_->IsLost()) - gpu_channel_ = NULL; - else - return gpu_channel_.get(); + gpu_channel_ = NULL; } - // Ensure initialization on the main thread. - GpuDataManagerImpl::GetInstance(); - EstablishRequest request(cause_for_gpu_launch); - GetIOLoopProxy()->PostTask( - FROM_HERE, - base::Bind( - &BrowserGpuChannelHostFactory::EstablishGpuChannelOnIO, - base::Unretained(this), - &request)); + if (!gpu_channel_ && !pending_request_) { + // We should only get here if the context was lost. + pending_request_ = new EstablishRequest( + cause_for_gpu_launch, gpu_client_id_, gpu_host_id_); + } - { - // We're blocking the UI thread, which is generally undesirable. - // In this case we need to wait for this before we can show any UI /anyway/, - // so it won't cause additional jank. - // TODO(piman): Make this asynchronous (http://crbug.com/125248). - base::ThreadRestrictions::ScopedAllowWait allow_wait; - request.event.Wait(); + if (!callback.is_null()) { + if (gpu_channel_) + callback.Run(); + else + established_callbacks_.push_back(callback); } +} - if (request.channel_handle.name.empty()) - return NULL; +GpuChannelHost* BrowserGpuChannelHostFactory::GetGpuChannel() { + if (gpu_channel_ && !gpu_channel_->IsLost()) + return gpu_channel_; - GetContentClient()->SetGpuInfo(request.gpu_info); - gpu_channel_ = GpuChannelHost::Create( - this, request.gpu_host_id, gpu_client_id_, - request.gpu_info, request.channel_handle); - return gpu_channel_.get(); + return NULL; +} + +void BrowserGpuChannelHostFactory::GpuChannelEstablished() { + DCHECK(IsMainThread()); + DCHECK(pending_request_); + if (pending_request_->channel_handle().name.empty()) + return; + + GetContentClient()->SetGpuInfo(pending_request_->gpu_info()); + gpu_channel_ = GpuChannelHost::Create(this, + pending_request_->gpu_host_id(), + gpu_client_id_, + pending_request_->gpu_info(), + pending_request_->channel_handle()); + gpu_host_id_ = pending_request_->gpu_host_id(); + pending_request_ = NULL; + + for (size_t n = 0; n < established_callbacks_.size(); n++) + established_callbacks_[n].Run(); + + established_callbacks_.clear(); } // static diff --git a/content/browser/gpu/browser_gpu_channel_host_factory.h b/content/browser/gpu/browser_gpu_channel_host_factory.h index ca31183..1944155 100644 --- a/content/browser/gpu/browser_gpu_channel_host_factory.h +++ b/content/browser/gpu/browser_gpu_channel_host_factory.h @@ -5,6 +5,8 @@ #ifndef CONTENT_BROWSER_GPU_BROWSER_GPU_CHANNEL_HOST_FACTORY_H_ #define CONTENT_BROWSER_GPU_BROWSER_GPU_CHANNEL_HOST_FACTORY_H_ +#include <vector> + #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" #include "base/process/process.h" @@ -17,7 +19,7 @@ namespace content { class CONTENT_EXPORT BrowserGpuChannelHostFactory : public GpuChannelHostFactory { public: - static void Initialize(); + static void Initialize(bool establish_gpu_channel); static void Terminate(); static BrowserGpuChannelHostFactory* instance() { return instance_; } @@ -36,8 +38,6 @@ class CONTENT_EXPORT BrowserGpuChannelHostFactory int32 image_id, const CreateImageCallback& callback) OVERRIDE; virtual void DeleteImage(int32 image_idu, int32 sync_point) OVERRIDE; - virtual GpuChannelHost* EstablishGpuChannelSync( - CauseForGpuLaunch cause_for_gpu_launch) OVERRIDE; // Specify a task runner and callback to be used for a set of messages. The // callback will be set up on the current GpuProcessHost, identified by @@ -48,6 +48,11 @@ class CONTENT_EXPORT BrowserGpuChannelHostFactory const base::Callback<void(const IPC::Message&)>& handler, base::TaskRunner* target_task_runner); int GpuProcessHostId() { return gpu_host_id_; } + GpuChannelHost* EstablishGpuChannelSync( + CauseForGpuLaunch cause_for_gpu_launch); + void EstablishGpuChannel(CauseForGpuLaunch cause_for_gpu_launch, + const base::Closure& callback); + GpuChannelHost* GetGpuChannel(); private: struct CreateRequest { @@ -58,20 +63,42 @@ class CONTENT_EXPORT BrowserGpuChannelHostFactory int32 route_id; }; - struct EstablishRequest { - explicit EstablishRequest(CauseForGpuLaunch); + class EstablishRequest : public base::RefCountedThreadSafe<EstablishRequest> { + public: + explicit EstablishRequest(CauseForGpuLaunch cause, + int gpu_client_id, + int gpu_host_id); + void Wait(); + void Cancel(); + + int gpu_host_id() { return gpu_host_id_; } + IPC::ChannelHandle& channel_handle() { return channel_handle_; } + gpu::GPUInfo gpu_info() { return gpu_info_; } + + private: + friend class base::RefCountedThreadSafe<EstablishRequest>; ~EstablishRequest(); - base::WaitableEvent event; - CauseForGpuLaunch cause_for_gpu_launch; - int gpu_host_id; - bool reused_gpu_process; - IPC::ChannelHandle channel_handle; - gpu::GPUInfo gpu_info; + void EstablishOnIO(); + void OnEstablishedOnIO(const IPC::ChannelHandle& channel_handle, + const gpu::GPUInfo& gpu_info); + void FinishOnIO(); + void FinishOnMain(); + + base::WaitableEvent event_; + CauseForGpuLaunch cause_for_gpu_launch_; + int gpu_client_id_; + int gpu_host_id_; + bool reused_gpu_process_; + IPC::ChannelHandle channel_handle_; + gpu::GPUInfo gpu_info_; + bool finished_; + scoped_refptr<base::MessageLoopProxy> main_loop_; }; - BrowserGpuChannelHostFactory(); + explicit BrowserGpuChannelHostFactory(bool establish_gpu_channel); virtual ~BrowserGpuChannelHostFactory(); + void GpuChannelEstablished(); void CreateViewCommandBufferOnIO( CreateRequest* request, int32 surface_id, @@ -86,11 +113,6 @@ class CONTENT_EXPORT BrowserGpuChannelHostFactory static void OnImageCreated( const CreateImageCallback& callback, const gfx::Size size); void DeleteImageOnIO(int32 image_id, int32 sync_point); - void EstablishGpuChannelOnIO(EstablishRequest* request); - void GpuChannelEstablishedOnIO( - EstablishRequest* request, - const IPC::ChannelHandle& channel_handle, - const gpu::GPUInfo& gpu_info); static void AddFilterOnIO( int gpu_host_id, scoped_refptr<IPC::ChannelProxy::MessageFilter> filter); @@ -99,6 +121,8 @@ class CONTENT_EXPORT BrowserGpuChannelHostFactory scoped_ptr<base::WaitableEvent> shutdown_event_; scoped_refptr<GpuChannelHost> gpu_channel_; int gpu_host_id_; + scoped_refptr<EstablishRequest> pending_request_; + std::vector<base::Closure> established_callbacks_; static BrowserGpuChannelHostFactory* instance_; diff --git a/content/browser/gpu/gpu_ipc_browsertests.cc b/content/browser/gpu/gpu_ipc_browsertests.cc index 0ee93db..3fda855 100644 --- a/content/browser/gpu/gpu_ipc_browsertests.cc +++ b/content/browser/gpu/gpu_ipc_browsertests.cc @@ -3,8 +3,13 @@ // found in the LICENSE file. #include "base/command_line.h" +#include "base/run_loop.h" #include "content/browser/gpu/browser_gpu_channel_host_factory.h" +#include "content/browser/gpu/gpu_process_host_ui_shim.h" +#include "content/common/gpu/client/context_provider_command_buffer.h" #include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h" +#include "content/common/gpu/gpu_process_launch_causes.h" +#include "content/public/browser/browser_thread.h" #include "content/public/common/content_switches.h" #include "content/test/content_browser_test.h" #include "ui/gl/gl_switches.h" @@ -15,10 +20,19 @@ namespace { class ContextTestBase : public content::ContentBrowserTest { public: virtual void SetUpOnMainThread() OVERRIDE { - CHECK(content::BrowserGpuChannelHostFactory::instance()); + if (!content::BrowserGpuChannelHostFactory::instance()) + content::BrowserGpuChannelHostFactory::Initialize(true); + + content::BrowserGpuChannelHostFactory* factory = + content::BrowserGpuChannelHostFactory::instance(); + CHECK(factory); + scoped_refptr<content::GpuChannelHost> gpu_channel_host( + factory->EstablishGpuChannelSync( + content:: + CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE)); context_.reset( content::WebGraphicsContext3DCommandBufferImpl::CreateOffscreenContext( - content::BrowserGpuChannelHostFactory::instance(), + gpu_channel_host.get(), WebKit::WebGraphicsContext3D::Attributes(), GURL())); CHECK(context_.get()); @@ -38,6 +52,133 @@ class ContextTestBase : public content::ContentBrowserTest { } // namespace -// Include the actual tests. +// Include the shared tests. #define CONTEXT_TEST_F IN_PROC_BROWSER_TEST_F #include "content/common/gpu/client/gpu_context_tests.h" + +namespace content { + +class BrowserGpuChannelHostFactoryTest : public ContextTestBase { + public: + virtual void SetUpOnMainThread() OVERRIDE { + // Start all tests without a gpu channel so that the tests exercise a + // consistent codepath. + if (!content::BrowserGpuChannelHostFactory::instance()) + content::BrowserGpuChannelHostFactory::Initialize(false); + + CHECK(GetFactory()); + + ContentBrowserTest::SetUpOnMainThread(); + } + + virtual void TearDownOnMainThread() OVERRIDE { + ContextTestBase::TearDownOnMainThread(); + } + + virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { + // Start all tests without a gpu channel so that the tests exercise a + // consistent codepath. + command_line->AppendSwitch(switches::kDisableGpuProcessPrelaunch); + } + + void OnContextLost(const base::Closure callback, int* counter) { + (*counter)++; + callback.Run(); + } + + protected: + BrowserGpuChannelHostFactory* GetFactory() { + return BrowserGpuChannelHostFactory::instance(); + } + + bool IsChannelEstablished() { + return GetFactory()->GetGpuChannel() != NULL; + } + + void EstablishAndWait() { + base::RunLoop run_loop; + GetFactory()->EstablishGpuChannel( + CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE, + run_loop.QuitClosure()); + run_loop.Run(); + } + + GpuChannelHost* GetGpuChannel() { + return GetFactory()->GetGpuChannel(); + } + + static void Signal(bool *event) { + CHECK_EQ(*event, false); + *event = true; + } + + scoped_ptr<WebGraphicsContext3DCommandBufferImpl> CreateContext() { + return make_scoped_ptr( + WebGraphicsContext3DCommandBufferImpl::CreateOffscreenContext( + GetGpuChannel(), + WebKit::WebGraphicsContext3D::Attributes(), + GURL())); + } +}; + +IN_PROC_BROWSER_TEST_F(BrowserGpuChannelHostFactoryTest, Basic) { + DCHECK(!IsChannelEstablished()); + EstablishAndWait(); + EXPECT_TRUE(GetGpuChannel() != NULL); +} + +IN_PROC_BROWSER_TEST_F(BrowserGpuChannelHostFactoryTest, + EstablishAndTerminate) { + DCHECK(!IsChannelEstablished()); + base::RunLoop run_loop; + GetFactory()->EstablishGpuChannel( + CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE, + run_loop.QuitClosure()); + GetFactory()->Terminate(); + + // The callback should still trigger. + run_loop.Run(); +} + +IN_PROC_BROWSER_TEST_F(BrowserGpuChannelHostFactoryTest, AlreadyEstablished) { + DCHECK(!IsChannelEstablished()); + scoped_refptr<GpuChannelHost> gpu_channel = + GetFactory()->EstablishGpuChannelSync( + CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE); + + // Expect established callback immediately. + bool event = false; + GetFactory()->EstablishGpuChannel( + CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE, + base::Bind(&BrowserGpuChannelHostFactoryTest::Signal, &event)); + EXPECT_TRUE(event); + EXPECT_EQ(gpu_channel, GetGpuChannel()); +} + +IN_PROC_BROWSER_TEST_F(BrowserGpuChannelHostFactoryTest, CrashAndRecover) { + DCHECK(!IsChannelEstablished()); + EstablishAndWait(); + scoped_refptr<GpuChannelHost> host = GetGpuChannel(); + + scoped_refptr<ContextProviderCommandBuffer> provider = + ContextProviderCommandBuffer::Create(CreateContext(), + "BrowserGpuChannelHostFactoryTest"); + base::RunLoop run_loop; + int counter = 0; + provider->SetLostContextCallback( + base::Bind(&BrowserGpuChannelHostFactoryTest::OnContextLost, + base::Unretained(this), run_loop.QuitClosure(), &counter)); + EXPECT_TRUE(provider->BindToCurrentThread()); + GpuProcessHostUIShim* shim = + GpuProcessHostUIShim::FromID(GetFactory()->GpuProcessHostId()); + EXPECT_TRUE(shim != NULL); + shim->SimulateCrash(); + run_loop.Run(); + + EXPECT_EQ(1, counter); + EXPECT_FALSE(IsChannelEstablished()); + EstablishAndWait(); + EXPECT_TRUE(IsChannelEstablished()); +} + +} // namespace content diff --git a/content/browser/renderer_host/compositor_impl_android.cc b/content/browser/renderer_host/compositor_impl_android.cc index da0c00f..f0d1ed9 100644 --- a/content/browser/renderer_host/compositor_impl_android.cc +++ b/content/browser/renderer_host/compositor_impl_android.cc @@ -358,34 +358,35 @@ CreateGpuProcessViewContext( const WebKit::WebGraphicsContext3D::Attributes attributes, int surface_id, base::WeakPtr<CompositorImpl> compositor_impl) { - GpuChannelHostFactory* factory = BrowserGpuChannelHostFactory::instance(); + BrowserGpuChannelHostFactory* factory = + BrowserGpuChannelHostFactory::instance(); + scoped_refptr<GpuChannelHost> gpu_channel_host(factory->EstablishGpuChannelSync( + CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE)); + if (!gpu_channel_host) + return scoped_ptr<WebGraphicsContext3DCommandBufferImpl>(); + GURL url("chrome://gpu/Compositor::createContext3D"); - scoped_ptr<WebGraphicsContext3DCommandBufferImpl> context( - new WebGraphicsContext3DCommandBufferImpl(surface_id, - url, - factory, - compositor_impl)); static const size_t kBytesPerPixel = 4; gfx::DeviceDisplayInfo display_info; size_t full_screen_texture_size_in_bytes = display_info.GetDisplayHeight() * display_info.GetDisplayWidth() * kBytesPerPixel; - if (!context->Initialize( - attributes, - false, - CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE, - 64 * 1024, // command buffer size - 64 * 1024, // start transfer buffer size - 64 * 1024, // min transfer buffer size - std::min(3 * full_screen_texture_size_in_bytes, - kDefaultMaxTransferBufferSize), - 2 * 1024 * 1024 // mapped memory limit - )) { - LOG(ERROR) << "Failed to create 3D context for compositor."; - return scoped_ptr<WebGraphicsContext3DCommandBufferImpl>(); - } - return context.Pass(); + WebGraphicsContext3DCommandBufferImpl::SharedMemoryLimits limits; + limits.command_buffer_size = 64 * 1024; + limits.start_transfer_buffer_size = 64 * 1024; + limits.min_transfer_buffer_size = 64 * 1024; + limits.max_transfer_buffer_size = std::min( + 3 * full_screen_texture_size_in_bytes, kDefaultMaxTransferBufferSize); + limits.mapped_memory_reclaim_limit = 2 * 1024 * 1024; + return make_scoped_ptr( + new WebGraphicsContext3DCommandBufferImpl(surface_id, + url, + gpu_channel_host.get(), + compositor_impl, + attributes, + false, + limits)); } scoped_ptr<cc::OutputSurface> CompositorImpl::CreateOutputSurface( diff --git a/content/browser/renderer_host/image_transport_factory_android.cc b/content/browser/renderer_host/image_transport_factory_android.cc index acfe2a0..9807366 100644 --- a/content/browser/renderer_host/image_transport_factory_android.cc +++ b/content/browser/renderer_host/image_transport_factory_android.cc @@ -56,34 +56,38 @@ class CmdBufferImageTransportFactory : public ImageTransportFactoryAndroid { }; CmdBufferImageTransportFactory::CmdBufferImageTransportFactory() { + BrowserGpuChannelHostFactory* factory = + BrowserGpuChannelHostFactory::instance(); + scoped_refptr<GpuChannelHost> gpu_channel_host(factory->EstablishGpuChannelSync( + CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE)); + DCHECK(gpu_channel_host); + WebKit::WebGraphicsContext3D::Attributes attrs; attrs.shareResources = true; - GpuChannelHostFactory* factory = BrowserGpuChannelHostFactory::instance(); GURL url("chrome://gpu/ImageTransportFactoryAndroid"); base::WeakPtr<WebGraphicsContext3DSwapBuffersClient> swap_client; - context_.reset(new WebGraphicsContext3DCommandBufferImpl(0, // offscreen - url, - factory, - swap_client)); static const size_t kBytesPerPixel = 4; gfx::DeviceDisplayInfo display_info; - size_t full_screen_texture_size_in_bytes = - display_info.GetDisplayHeight() * - display_info.GetDisplayWidth() * - kBytesPerPixel; + size_t full_screen_texture_size_in_bytes = display_info.GetDisplayHeight() * + display_info.GetDisplayWidth() * + kBytesPerPixel; + WebGraphicsContext3DCommandBufferImpl::SharedMemoryLimits limits; + limits.command_buffer_size = 64 * 1024; + limits.start_transfer_buffer_size = 64 * 1024; + limits.min_transfer_buffer_size = 64 * 1024; + limits.max_transfer_buffer_size = std::min( + 3 * full_screen_texture_size_in_bytes, kDefaultMaxTransferBufferSize); + limits.mapped_memory_reclaim_limit = + WebGraphicsContext3DCommandBufferImpl::kNoLimit; + context_.reset( + new WebGraphicsContext3DCommandBufferImpl(0, // offscreen + url, + gpu_channel_host.get(), + swap_client, + attrs, + false, + limits)); context_->setContextLostCallback(context_lost_listener_.get()); - context_->Initialize( - attrs, - false, - CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE, - 64 * 1024, // command buffer size - 64 * 1024, // starting buffer size - 64 * 1024, // min buffer size - std::min(3 * full_screen_texture_size_in_bytes, - kDefaultMaxTransferBufferSize), - WebGraphicsContext3DCommandBufferImpl::kNoLimit - ); - if (context_->makeContextCurrent()) context_->pushGroupMarkerEXT( base::StringPrintf("CmdBufferImageTransportFactory-%p", diff --git a/content/common/gpu/client/context_provider_command_buffer_browsertest.cc b/content/common/gpu/client/context_provider_command_buffer_browsertest.cc index fd68aa4..e58e5d8 100644 --- a/content/common/gpu/client/context_provider_command_buffer_browsertest.cc +++ b/content/common/gpu/client/context_provider_command_buffer_browsertest.cc @@ -12,11 +12,27 @@ namespace content { namespace { class ContextProviderCommandBufferBrowserTest : public ContentBrowserTest { + public: + virtual void SetUpOnMainThread() OVERRIDE { + if (!GetFactory()) + BrowserGpuChannelHostFactory::Initialize(true); + + CHECK(GetFactory()); + ContentBrowserTest::SetUpOnMainThread(); + } + protected: + BrowserGpuChannelHostFactory* GetFactory() { + return BrowserGpuChannelHostFactory::instance(); + } + scoped_ptr<WebGraphicsContext3DCommandBufferImpl> CreateContext3d() { + scoped_refptr<GpuChannelHost> gpu_channel_host( + GetFactory()->EstablishGpuChannelSync( + CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE)); scoped_ptr<WebGraphicsContext3DCommandBufferImpl> context( WebGraphicsContext3DCommandBufferImpl::CreateOffscreenContext( - BrowserGpuChannelHostFactory::instance(), + gpu_channel_host.get(), WebKit::WebGraphicsContext3D::Attributes(), GURL("chrome://gpu/ContextProviderCommandBufferTest"))); return context.Pass(); diff --git a/content/common/gpu/client/gpu_channel_host.h b/content/common/gpu/client/gpu_channel_host.h index 5efa98d..d6e7ef3 100644 --- a/content/common/gpu/client/gpu_channel_host.h +++ b/content/common/gpu/client/gpu_channel_host.h @@ -71,7 +71,6 @@ class CONTENT_EXPORT GpuChannelHostFactory { virtual scoped_ptr<base::SharedMemory> AllocateSharedMemory(size_t size) = 0; virtual int32 CreateViewCommandBuffer( int32 surface_id, const GPUCreateCommandBufferConfig& init_params) = 0; - virtual GpuChannelHost* EstablishGpuChannelSync(CauseForGpuLaunch) = 0; virtual void CreateImage( gfx::PluginWindowHandle window, int32 image_id, diff --git a/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.cc b/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.cc index c46c688..2087def 100644 --- a/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.cc +++ b/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.cc @@ -25,7 +25,6 @@ #include "base/synchronization/lock.h" #include "content/common/gpu/client/gpu_channel_host.h" #include "content/common/gpu/gpu_memory_allocation.h" -#include "content/common/gpu/gpu_process_launch_causes.h" #include "content/public/common/content_constants.h" #include "content/public/common/content_switches.h" #include "gpu/GLES2/gl2extchromium.h" @@ -213,16 +212,25 @@ void WebGraphicsContext3DErrorMessageCallback::OnErrorMessage( graphics_context_->OnErrorMessage(msg, id); } +WebGraphicsContext3DCommandBufferImpl::SharedMemoryLimits::SharedMemoryLimits() + : command_buffer_size(kDefaultCommandBufferSize), + start_transfer_buffer_size(kDefaultStartTransferBufferSize), + min_transfer_buffer_size(kDefaultMinTransferBufferSize), + max_transfer_buffer_size(kDefaultMaxTransferBufferSize), + mapped_memory_reclaim_limit(gpu::gles2::GLES2Implementation::kNoLimit) {} + WebGraphicsContext3DCommandBufferImpl::WebGraphicsContext3DCommandBufferImpl( int surface_id, const GURL& active_url, - GpuChannelHostFactory* factory, - const base::WeakPtr<WebGraphicsContext3DSwapBuffersClient>& swap_client) + GpuChannelHost* host, + const base::WeakPtr<WebGraphicsContext3DSwapBuffersClient>& swap_client, + const Attributes& attributes, + bool bind_generates_resources, + const SharedMemoryLimits& limits) : initialize_failed_(false), - factory_(factory), visible_(false), free_command_buffer_when_invisible_(false), - host_(NULL), + host_(host), surface_id_(surface_id), active_url_(active_url), swap_client_(swap_client), @@ -230,18 +238,16 @@ WebGraphicsContext3DCommandBufferImpl::WebGraphicsContext3DCommandBufferImpl( context_lost_reason_(GL_NO_ERROR), error_message_callback_(0), swapbuffers_complete_callback_(0), - gpu_preference_(gfx::PreferIntegratedGpu), + attributes_(attributes), + gpu_preference_(attributes.preferDiscreteGPU ? gfx::PreferDiscreteGpu + : gfx::PreferIntegratedGpu), weak_ptr_factory_(this), initialized_(false), gl_(NULL), frame_number_(0), - bind_generates_resources_(false), + bind_generates_resources_(bind_generates_resources), use_echo_for_swap_ack_(true), - command_buffer_size_(0), - start_transfer_buffer_size_(0), - min_transfer_buffer_size_(0), - max_transfer_buffer_size_(0), - mapped_memory_limit_(gpu::gles2::GLES2Implementation::kNoLimit), + mem_limits_(limits), flush_id_(0) { #if (defined(OS_MACOSX) || defined(OS_WIN)) && !defined(USE_AURA) // Get ViewMsg_SwapBuffers_ACK from browser for single-threaded path. @@ -264,54 +270,6 @@ WebGraphicsContext3DCommandBufferImpl:: Destroy(); } -bool WebGraphicsContext3DCommandBufferImpl::InitializeWithDefaultBufferSizes( - const WebGraphicsContext3D::Attributes& attributes, - bool bind_generates_resources, - CauseForGpuLaunch cause) { - return Initialize(attributes, - bind_generates_resources, - cause, - kDefaultCommandBufferSize, - kDefaultStartTransferBufferSize, - kDefaultMinTransferBufferSize, - kDefaultMaxTransferBufferSize, - gpu::gles2::GLES2Implementation::kNoLimit); -} - -bool WebGraphicsContext3DCommandBufferImpl::Initialize( - const WebGraphicsContext3D::Attributes& attributes, - bool bind_generates_resources, - CauseForGpuLaunch cause, - size_t command_buffer_size, - size_t start_transfer_buffer_size, - size_t min_transfer_buffer_size, - size_t max_transfer_buffer_size, - size_t mapped_memory_limit) { - TRACE_EVENT0("gpu", "WebGfxCtx3DCmdBfrImpl::initialize"); - - attributes_ = attributes; - bind_generates_resources_ = bind_generates_resources; - DCHECK(!command_buffer_); - - if (!factory_) - return false; - - if (attributes.preferDiscreteGPU) - gpu_preference_ = gfx::PreferDiscreteGpu; - - host_ = factory_->EstablishGpuChannelSync(cause); - if (!host_.get()) - return false; - - command_buffer_size_ = command_buffer_size; - start_transfer_buffer_size_ = start_transfer_buffer_size; - min_transfer_buffer_size_ = min_transfer_buffer_size; - max_transfer_buffer_size_ = max_transfer_buffer_size; - mapped_memory_limit_ = mapped_memory_limit; - - return true; -} - bool WebGraphicsContext3DCommandBufferImpl::MaybeInitializeGL() { if (initialized_) return true; @@ -439,7 +397,7 @@ bool WebGraphicsContext3DCommandBufferImpl::CreateContext( // Create the GLES2 helper, which writes the command buffer protocol. gles2_helper_.reset(new gpu::gles2::GLES2CmdHelper(command_buffer_.get())); - if (!gles2_helper_->Initialize(command_buffer_size_)) + if (!gles2_helper_->Initialize(mem_limits_.command_buffer_size)) return false; if (attributes_.noAutomaticFlushes) @@ -478,10 +436,10 @@ bool WebGraphicsContext3DCommandBufferImpl::CreateContext( } if (!real_gl_->Initialize( - start_transfer_buffer_size_, - min_transfer_buffer_size_, - max_transfer_buffer_size_, - mapped_memory_limit_)) { + mem_limits_.start_transfer_buffer_size, + mem_limits_.min_transfer_buffer_size, + mem_limits_.max_transfer_buffer_size, + mem_limits_.mapped_memory_reclaim_limit)) { return false; } @@ -1269,7 +1227,7 @@ void WebGraphicsContext3DCommandBufferImpl::deleteTexture(WebGLId texture) { } bool WebGraphicsContext3DCommandBufferImpl::ShouldUseSwapClient() { - return factory_ && factory_->IsMainThread() && swap_client_.get(); + return !!swap_client_.get(); } void WebGraphicsContext3DCommandBufferImpl::OnSwapBuffersComplete() { @@ -1367,20 +1325,19 @@ bool WebGraphicsContext3DCommandBufferImpl::IsCommandBufferContextLost() { // static WebGraphicsContext3DCommandBufferImpl* WebGraphicsContext3DCommandBufferImpl::CreateOffscreenContext( - GpuChannelHostFactory* factory, + GpuChannelHost* host, const WebGraphicsContext3D::Attributes& attributes, const GURL& active_url) { - if (!factory) + if (!host) return NULL; base::WeakPtr<WebGraphicsContext3DSwapBuffersClient> null_client; - scoped_ptr<WebGraphicsContext3DCommandBufferImpl> context( - new WebGraphicsContext3DCommandBufferImpl( - 0, active_url, factory, null_client)); - CauseForGpuLaunch cause = - CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE; - if (context->InitializeWithDefaultBufferSizes(attributes, false, cause)) - return context.release(); - return NULL; + return new WebGraphicsContext3DCommandBufferImpl(0, + active_url, + host, + null_client, + attributes, + false, + SharedMemoryLimits()); } void WebGraphicsContext3DCommandBufferImpl:: diff --git a/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h b/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h index e571eda..21a9598 100644 --- a/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h +++ b/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h @@ -13,7 +13,6 @@ #include "base/memory/weak_ptr.h" #include "content/common/content_export.h" #include "content/common/gpu/client/command_buffer_proxy_impl.h" -#include "content/common/gpu/gpu_process_launch_causes.h" #include "third_party/WebKit/public/platform/WebGraphicsContext3D.h" #include "third_party/WebKit/public/platform/WebString.h" #include "ui/gfx/native_widget_types.h" @@ -50,7 +49,6 @@ using WebKit::WebGraphicsMemoryAllocation; namespace content { class GpuChannelHost; -class GpuChannelHostFactory; struct GpuMemoryAllocationForRenderer; const size_t kDefaultCommandBufferSize = 1024 * 1024; @@ -79,27 +77,27 @@ class WebGraphicsContext3DCommandBufferImpl kNoLimit = 0, }; + struct SharedMemoryLimits { + SharedMemoryLimits(); + + size_t command_buffer_size; + size_t start_transfer_buffer_size; + size_t min_transfer_buffer_size; + size_t max_transfer_buffer_size; + size_t mapped_memory_reclaim_limit; + }; + WebGraphicsContext3DCommandBufferImpl( int surface_id, const GURL& active_url, - GpuChannelHostFactory* factory, - const base::WeakPtr<WebGraphicsContext3DSwapBuffersClient>& swap_client); + GpuChannelHost* host, + const base::WeakPtr<WebGraphicsContext3DSwapBuffersClient>& swap_client, + const Attributes& attributes, + bool bind_generates_resources, + const SharedMemoryLimits& limits); virtual ~WebGraphicsContext3DCommandBufferImpl(); - bool Initialize(const Attributes& attributes, - bool bind_generates_resources, - CauseForGpuLaunch cause, - size_t command_buffer_size, - size_t start_transfer_buffer_size, - size_t min_transfer_buffer_size, - size_t max_transfer_buffer_size, - size_t mapped_memory_reclaim_limit); - - bool InitializeWithDefaultBufferSizes(const Attributes& attributes, - bool bind_generates_resources, - CauseForGpuLaunch cause); - // The following 3 IDs let one uniquely identify this context. // Gets the GPU process ID for this context. int GetGPUProcessID(); @@ -126,12 +124,12 @@ class WebGraphicsContext3DCommandBufferImpl // on any failure. static CONTENT_EXPORT WebGraphicsContext3DCommandBufferImpl* CreateOffscreenContext( - GpuChannelHostFactory* factory, + GpuChannelHost* host, const WebGraphicsContext3D::Attributes& attributes, const GURL& active_url); size_t GetMappedMemoryLimit() { - return mapped_memory_limit_; + return mem_limits_.mapped_memory_reclaim_limit; } //---------------------------------------------------------------------- @@ -712,9 +710,6 @@ class WebGraphicsContext3DCommandBufferImpl bool initialize_failed_; - // The channel factory to talk to the GPU process - GpuChannelHostFactory* factory_; - bool visible_; bool free_command_buffer_when_invisible_; @@ -754,11 +749,7 @@ class WebGraphicsContext3DCommandBufferImpl int frame_number_; bool bind_generates_resources_; bool use_echo_for_swap_ack_; - size_t command_buffer_size_; - size_t start_transfer_buffer_size_; - size_t min_transfer_buffer_size_; - size_t max_transfer_buffer_size_; - size_t mapped_memory_limit_; + SharedMemoryLimits mem_limits_; uint32_t flush_id_; }; diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc index 1eb2c21..cc83b35 100644 --- a/content/renderer/render_thread_impl.cc +++ b/content/renderer/render_thread_impl.cc @@ -45,6 +45,7 @@ #include "content/common/gpu/client/context_provider_command_buffer.h" #include "content/common/gpu/client/gpu_channel_host.h" #include "content/common/gpu/gpu_messages.h" +#include "content/common/gpu/gpu_process_launch_causes.h" #include "content/common/resource_messages.h" #include "content/common/view_messages.h" #include "content/public/common/content_constants.h" @@ -874,24 +875,28 @@ RenderThreadImpl::GetGpuFactories( const scoped_refptr<base::MessageLoopProxy>& factories_loop) { DCHECK(IsMainThread()); + scoped_refptr<GpuChannelHost> gpu_channel_host = GetGpuChannel(); const CommandLine* cmd_line = CommandLine::ForCurrentProcess(); scoped_refptr<RendererGpuVideoAcceleratorFactories> gpu_factories; if (!cmd_line->HasSwitch(switches::kDisableAcceleratedVideoDecode)) { if (!gpu_va_context_provider_ || gpu_va_context_provider_->DestroyedOnMainThread()) { + if (!gpu_channel_host) { + gpu_channel_host = EstablishGpuChannelSync( + CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE); + } gpu_va_context_provider_ = ContextProviderCommandBuffer::Create( make_scoped_ptr( WebGraphicsContext3DCommandBufferImpl::CreateOffscreenContext( - this, + gpu_channel_host.get(), WebKit::WebGraphicsContext3D::Attributes(), GURL("chrome://gpu/RenderThreadImpl::GetGpuVDAContext3D"))), "GPU-VideoAccelerator-Offscreen"); } } - GpuChannelHost* gpu_channel_host = GetGpuChannel(); if (gpu_channel_host) { gpu_factories = new RendererGpuVideoAcceleratorFactories( - gpu_channel_host, factories_loop, gpu_va_context_provider_); + gpu_channel_host.get(), factories_loop, gpu_va_context_provider_); } return gpu_factories; } @@ -905,9 +910,11 @@ RenderThreadImpl::CreateOffscreenContext3d() { attributes.antialias = false; attributes.noAutomaticFlushes = true; + scoped_refptr<GpuChannelHost> gpu_channel_host(EstablishGpuChannelSync( + CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE)); return make_scoped_ptr( WebGraphicsContext3DCommandBufferImpl::CreateOffscreenContext( - this, + gpu_channel_host.get(), attributes, GURL("chrome://gpu/RenderThreadImpl::CreateOffscreenContext3d"))); } diff --git a/content/renderer/render_thread_impl.h b/content/renderer/render_thread_impl.h index aea1836..678d06f 100644 --- a/content/renderer/render_thread_impl.h +++ b/content/renderer/render_thread_impl.h @@ -18,7 +18,6 @@ #include "content/child/child_thread.h" #include "content/common/content_export.h" #include "content/common/gpu/client/gpu_channel_host.h" -#include "content/common/gpu/gpu_process_launch_causes.h" #include "content/public/renderer/render_thread.h" #include "content/renderer/media/renderer_gpu_video_accelerator_factories.h" #include "ipc/ipc_channel_proxy.h" @@ -165,7 +164,7 @@ class CONTENT_EXPORT RenderThreadImpl : public RenderThread, // established or if it has been lost (for example if the GPU plugin crashed). // If there is a pending asynchronous request, it will be completed by the // time this routine returns. - virtual GpuChannelHost* EstablishGpuChannelSync(CauseForGpuLaunch) OVERRIDE; + GpuChannelHost* EstablishGpuChannelSync(CauseForGpuLaunch); // These methods modify how the next message is sent. Normally, when sending diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc index 1cb162a..241cab4 100644 --- a/content/renderer/render_widget.cc +++ b/content/renderer/render_widget.cc @@ -22,6 +22,7 @@ #include "content/child/npapi/webplugin.h" #include "content/common/gpu/client/context_provider_command_buffer.h" #include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h" +#include "content/common/gpu/gpu_process_launch_causes.h" #include "content/common/input_messages.h" #include "content/common/swapped_out_messages.h" #include "content/common/view_messages.h" @@ -2796,13 +2797,13 @@ RenderWidget::CreateGraphicsContext3D( if (CommandLine::ForCurrentProcess()->HasSwitch( switches::kDisableGpuCompositing)) return scoped_ptr<WebGraphicsContext3DCommandBufferImpl>(); - scoped_ptr<WebGraphicsContext3DCommandBufferImpl> context( - new WebGraphicsContext3DCommandBufferImpl( - surface_id(), - GetURLForGraphicsContext3D(), - RenderThreadImpl::current(), - weak_ptr_factory_.GetWeakPtr())); + scoped_refptr<GpuChannelHost> gpu_channel_host( + RenderThreadImpl::current()->EstablishGpuChannelSync( + CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE)); + if (!gpu_channel_host) + return scoped_ptr<WebGraphicsContext3DCommandBufferImpl>(); + WebGraphicsContext3DCommandBufferImpl::SharedMemoryLimits limits; #if defined(OS_ANDROID) // If we raster too fast we become upload bound, and pending // uploads consume memory. For maximum upload throughput, we would @@ -2822,22 +2823,23 @@ RenderWidget::CreateGraphicsContext3D( static const size_t kBytesPerMegabyte = 1024 * 1024; // We keep the MappedMemoryReclaimLimit the same as the upload limit // to avoid unnecessarily stalling the compositor thread. - const size_t mapped_memory_reclaim_limit = + limits.mapped_memory_reclaim_limit = max_transfer_buffer_usage_mb * kBytesPerMegabyte; -#else - const size_t mapped_memory_reclaim_limit = - WebGraphicsContext3DCommandBufferImpl::kNoLimit; #endif - if (!context->Initialize( + + base::WeakPtr<WebGraphicsContext3DSwapBuffersClient> swap_client; + if (!is_threaded_compositing_enabled_) + swap_client = weak_ptr_factory_.GetWeakPtr(); + + scoped_ptr<WebGraphicsContext3DCommandBufferImpl> context( + new WebGraphicsContext3DCommandBufferImpl( + surface_id(), + GetURLForGraphicsContext3D(), + gpu_channel_host.get(), + swap_client, attributes, false /* bind generates resources */, - CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE, - kDefaultCommandBufferSize, - kDefaultStartTransferBufferSize, - kDefaultMinTransferBufferSize, - kDefaultMaxTransferBufferSize, - mapped_memory_reclaim_limit)) - return scoped_ptr<WebGraphicsContext3DCommandBufferImpl>(); + limits)); return context.Pass(); } diff --git a/content/renderer/renderer_webkitplatformsupport_impl.cc b/content/renderer/renderer_webkitplatformsupport_impl.cc index fce9f2b..105ab27 100644 --- a/content/renderer/renderer_webkitplatformsupport_impl.cc +++ b/content/renderer/renderer_webkitplatformsupport_impl.cc @@ -25,7 +25,9 @@ #include "content/child/webmessageportchannel_impl.h" #include "content/common/file_utilities_messages.h" #include "content/common/gpu/client/context_provider_command_buffer.h" +#include "content/common/gpu/client/gpu_channel_host.h" #include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h" +#include "content/common/gpu/gpu_process_launch_causes.h" #include "content/common/mime_registry_messages.h" #include "content/common/view_messages.h" #include "content/public/common/content_switches.h" @@ -936,8 +938,11 @@ bool RendererWebKitPlatformSupportImpl::processMemorySizesInBytes( WebKit::WebGraphicsContext3D* RendererWebKitPlatformSupportImpl::createOffscreenGraphicsContext3D( const WebKit::WebGraphicsContext3D::Attributes& attributes) { + scoped_refptr<GpuChannelHost> gpu_channel_host( + RenderThreadImpl::current()->EstablishGpuChannelSync( + CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE)); return WebGraphicsContext3DCommandBufferImpl::CreateOffscreenContext( - RenderThreadImpl::current(), + gpu_channel_host.get(), attributes, GURL(attributes.topDocumentURL)); } |