diff options
author | sievers@chromium.org <sievers@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-10-15 21:59:24 +0000 |
---|---|---|
committer | sievers@chromium.org <sievers@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-10-15 21:59:24 +0000 |
commit | 9cf895b669bc8f28b173816f3b3332f33c64d771 (patch) | |
tree | 72cf41418451a56da58d253fa6fb4ad7f863ce9e | |
parent | c8fafab0cc74036e8c8b7c59615a4d3ab0bd1018 (diff) | |
download | chromium_src-9cf895b669bc8f28b173816f3b3332f33c64d771.zip chromium_src-9cf895b669bc8f28b173816f3b3332f33c64d771.tar.gz chromium_src-9cf895b669bc8f28b173816f3b3332f33c64d771.tar.bz2 |
Allow asynchronous GPU context creation for browser clients
This moves the call to establish a GPU channel out of WGC3D.
It adds an asynchronous method to BrowserGpuChannelHostFactory
that registers callbacks that are run on the main thread once
the channel is established.
This is prerequisite work for asynchronous OutputSurface creation.
BUG=270179,125248,235300
R=piman@chromium.org
Review URL: https://codereview.chromium.org/26959002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@228777 0039d316-1c4b-4281-b951-d872f2087c98
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)); } |