1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/common/gpu/gpu_channel_manager.h"
8 #include "base/command_line.h"
9 #include "content/common/gpu/gpu_channel.h"
10 #include "content/common/gpu/gpu_memory_buffer_factory.h"
11 #include "content/common/gpu/gpu_memory_manager.h"
12 #include "content/common/gpu/gpu_messages.h"
13 #include "content/common/gpu/sync_point_manager.h"
14 #include "content/common/message_router.h"
15 #include "gpu/command_buffer/service/feature_info.h"
16 #include "gpu/command_buffer/service/gpu_switches.h"
17 #include "gpu/command_buffer/service/mailbox_manager.h"
18 #include "gpu/command_buffer/service/memory_program_cache.h"
19 #include "gpu/command_buffer/service/shader_translator_cache.h"
20 #include "ipc/message_filter.h"
21 #include "ui/gl/gl_bindings.h"
22 #include "ui/gl/gl_share_group.h"
28 class GpuChannelManagerMessageFilter : public IPC::MessageFilter {
30 GpuChannelManagerMessageFilter(
31 GpuMemoryBufferFactory* gpu_memory_buffer_factory)
32 : sender_(NULL), gpu_memory_buffer_factory_(gpu_memory_buffer_factory) {}
34 virtual void OnFilterAdded(IPC::Sender* sender) OVERRIDE {
39 virtual void OnFilterRemoved() OVERRIDE {
44 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
47 IPC_BEGIN_MESSAGE_MAP(GpuChannelManagerMessageFilter, message)
48 IPC_MESSAGE_HANDLER(GpuMsg_CreateGpuMemoryBuffer, OnCreateGpuMemoryBuffer)
49 IPC_MESSAGE_UNHANDLED(handled = false)
55 virtual ~GpuChannelManagerMessageFilter() {}
57 void OnCreateGpuMemoryBuffer(const gfx::GpuMemoryBufferHandle& handle,
58 const gfx::Size& size,
59 unsigned internalformat,
62 "GpuChannelManagerMessageFilter::OnCreateGpuMemoryBuffer",
64 handle.global_id.primary_id,
66 handle.global_id.secondary_id);
67 sender_->Send(new GpuHostMsg_GpuMemoryBufferCreated(
68 gpu_memory_buffer_factory_->CreateGpuMemoryBuffer(
69 handle, size, internalformat, usage)));
73 GpuMemoryBufferFactory* gpu_memory_buffer_factory_;
78 GpuChannelManager::GpuChannelManager(MessageRouter* router,
79 GpuWatchdog* watchdog,
80 base::MessageLoopProxy* io_message_loop,
81 base::WaitableEvent* shutdown_event,
82 IPC::SyncChannel* channel)
83 : io_message_loop_(io_message_loop),
84 shutdown_event_(shutdown_event),
88 GpuMemoryManager::kDefaultMaxSurfacesWithFrontbufferSoftLimit),
90 sync_point_manager_(new SyncPointManager),
91 gpu_memory_buffer_factory_(GpuMemoryBufferFactory::Create()),
93 filter_(new GpuChannelManagerMessageFilter(
94 gpu_memory_buffer_factory_.get())),
97 DCHECK(io_message_loop);
98 DCHECK(shutdown_event);
99 channel_->AddFilter(filter_.get());
102 GpuChannelManager::~GpuChannelManager() {
103 gpu_channels_.clear();
104 if (default_offscreen_surface_.get()) {
105 default_offscreen_surface_->Destroy();
106 default_offscreen_surface_ = NULL;
110 gpu::gles2::ProgramCache* GpuChannelManager::program_cache() {
111 if (!program_cache_.get() &&
112 (gfx::g_driver_gl.ext.b_GL_ARB_get_program_binary ||
113 gfx::g_driver_gl.ext.b_GL_OES_get_program_binary) &&
114 !CommandLine::ForCurrentProcess()->HasSwitch(
115 switches::kDisableGpuProgramCache)) {
116 program_cache_.reset(new gpu::gles2::MemoryProgramCache());
118 return program_cache_.get();
121 gpu::gles2::ShaderTranslatorCache*
122 GpuChannelManager::shader_translator_cache() {
123 if (!shader_translator_cache_.get())
124 shader_translator_cache_ = new gpu::gles2::ShaderTranslatorCache;
125 return shader_translator_cache_.get();
128 void GpuChannelManager::RemoveChannel(int client_id) {
129 Send(new GpuHostMsg_DestroyChannel(client_id));
130 gpu_channels_.erase(client_id);
133 int GpuChannelManager::GenerateRouteID() {
134 static int last_id = 0;
138 void GpuChannelManager::AddRoute(int32 routing_id, IPC::Listener* listener) {
139 router_->AddRoute(routing_id, listener);
142 void GpuChannelManager::RemoveRoute(int32 routing_id) {
143 router_->RemoveRoute(routing_id);
146 GpuChannel* GpuChannelManager::LookupChannel(int32 client_id) {
147 GpuChannelMap::const_iterator iter = gpu_channels_.find(client_id);
148 if (iter == gpu_channels_.end())
154 bool GpuChannelManager::OnMessageReceived(const IPC::Message& msg) {
156 IPC_BEGIN_MESSAGE_MAP(GpuChannelManager, msg)
157 IPC_MESSAGE_HANDLER(GpuMsg_EstablishChannel, OnEstablishChannel)
158 IPC_MESSAGE_HANDLER(GpuMsg_CloseChannel, OnCloseChannel)
159 IPC_MESSAGE_HANDLER(GpuMsg_CreateViewCommandBuffer,
160 OnCreateViewCommandBuffer)
161 IPC_MESSAGE_HANDLER(GpuMsg_DestroyGpuMemoryBuffer, OnDestroyGpuMemoryBuffer)
162 IPC_MESSAGE_HANDLER(GpuMsg_LoadedShader, OnLoadedShader)
163 IPC_MESSAGE_UNHANDLED(handled = false)
164 IPC_END_MESSAGE_MAP()
168 bool GpuChannelManager::Send(IPC::Message* msg) { return router_->Send(msg); }
170 void GpuChannelManager::OnEstablishChannel(int client_id,
172 bool allow_future_sync_points) {
173 IPC::ChannelHandle channel_handle;
175 gfx::GLShareGroup* share_group = NULL;
176 gpu::gles2::MailboxManager* mailbox_manager = NULL;
178 if (!share_group_.get()) {
179 share_group_ = new gfx::GLShareGroup;
180 DCHECK(!mailbox_manager_.get());
181 mailbox_manager_ = new gpu::gles2::MailboxManager;
183 share_group = share_group_.get();
184 mailbox_manager = mailbox_manager_.get();
187 scoped_ptr<GpuChannel> channel(new GpuChannel(this,
193 allow_future_sync_points));
194 channel->Init(io_message_loop_.get(), shutdown_event_);
195 channel_handle.name = channel->GetChannelName();
197 #if defined(OS_POSIX)
198 // On POSIX, pass the renderer-side FD. Also mark it as auto-close so
199 // that it gets closed after it has been sent.
200 int renderer_fd = channel->TakeRendererFileDescriptor();
201 DCHECK_NE(-1, renderer_fd);
202 channel_handle.socket = base::FileDescriptor(renderer_fd, true);
205 gpu_channels_.set(client_id, channel.Pass());
207 Send(new GpuHostMsg_ChannelEstablished(channel_handle));
210 void GpuChannelManager::OnCloseChannel(
211 const IPC::ChannelHandle& channel_handle) {
212 for (GpuChannelMap::iterator iter = gpu_channels_.begin();
213 iter != gpu_channels_.end(); ++iter) {
214 if (iter->second->GetChannelName() == channel_handle.name) {
215 gpu_channels_.erase(iter);
221 void GpuChannelManager::OnCreateViewCommandBuffer(
222 const gfx::GLSurfaceHandle& window,
225 const GPUCreateCommandBufferConfig& init_params,
228 CreateCommandBufferResult result = CREATE_COMMAND_BUFFER_FAILED;
230 GpuChannelMap::const_iterator iter = gpu_channels_.find(client_id);
231 if (iter != gpu_channels_.end()) {
232 result = iter->second->CreateViewCommandBuffer(
233 window, surface_id, init_params, route_id);
236 Send(new GpuHostMsg_CommandBufferCreated(result));
238 void GpuChannelManager::DestroyGpuMemoryBuffer(
239 const gfx::GpuMemoryBufferHandle& handle) {
240 io_message_loop_->PostTask(
242 base::Bind(&GpuChannelManager::DestroyGpuMemoryBufferOnIO,
243 base::Unretained(this),
247 void GpuChannelManager::DestroyGpuMemoryBufferOnIO(
248 const gfx::GpuMemoryBufferHandle& handle) {
249 gpu_memory_buffer_factory_->DestroyGpuMemoryBuffer(handle);
252 void GpuChannelManager::OnDestroyGpuMemoryBuffer(
253 const gfx::GpuMemoryBufferHandle& handle,
256 DestroyGpuMemoryBuffer(handle);
258 sync_point_manager()->AddSyncPointCallback(
260 base::Bind(&GpuChannelManager::DestroyGpuMemoryBuffer,
261 base::Unretained(this),
266 void GpuChannelManager::OnLoadedShader(std::string program_proto) {
268 program_cache()->LoadProgram(program_proto);
271 bool GpuChannelManager::HandleMessagesScheduled() {
272 for (GpuChannelMap::iterator iter = gpu_channels_.begin();
273 iter != gpu_channels_.end(); ++iter) {
274 if (iter->second->handle_messages_scheduled())
280 uint64 GpuChannelManager::MessagesProcessed() {
281 uint64 messages_processed = 0;
283 for (GpuChannelMap::iterator iter = gpu_channels_.begin();
284 iter != gpu_channels_.end(); ++iter) {
285 messages_processed += iter->second->messages_processed();
287 return messages_processed;
290 void GpuChannelManager::LoseAllContexts() {
291 for (GpuChannelMap::iterator iter = gpu_channels_.begin();
292 iter != gpu_channels_.end(); ++iter) {
293 iter->second->MarkAllContextsLost();
295 base::MessageLoop::current()->PostTask(
297 base::Bind(&GpuChannelManager::OnLoseAllContexts,
298 weak_factory_.GetWeakPtr()));
301 void GpuChannelManager::OnLoseAllContexts() {
302 gpu_channels_.clear();
305 gfx::GLSurface* GpuChannelManager::GetDefaultOffscreenSurface() {
306 if (!default_offscreen_surface_.get()) {
307 default_offscreen_surface_ =
308 gfx::GLSurface::CreateOffscreenGLSurface(gfx::Size());
310 return default_offscreen_surface_.get();
313 } // namespace content