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. 4 5 #include "content/common/gpu/gpu_channel_manager.h" 6 7 #include "base/bind.h" 8 #include "base/command_line.h" 9 #include "content/common/gpu/gpu_channel.h" 10 #include "content/common/gpu/gpu_memory_manager.h" 11 #include "content/common/gpu/gpu_messages.h" 12 #include "content/common/gpu/sync_point_manager.h" 13 #include "content/common/message_router.h" 14 #include "gpu/command_buffer/service/feature_info.h" 15 #include "gpu/command_buffer/service/gpu_switches.h" 16 #include "gpu/command_buffer/service/mailbox_manager.h" 17 #include "gpu/command_buffer/service/memory_program_cache.h" 18 #include "gpu/command_buffer/service/shader_translator_cache.h" 19 #include "ui/gl/gl_bindings.h" 20 #include "ui/gl/gl_share_group.h" 21 22 namespace content { 23 24 GpuChannelManager::ImageOperation::ImageOperation( 25 int32 sync_point, base::Closure callback) 26 : sync_point(sync_point), 27 callback(callback) { 28 } 29 30 GpuChannelManager::ImageOperation::~ImageOperation() { 31 } 32 33 GpuChannelManager::GpuChannelManager(MessageRouter* router, 34 GpuWatchdog* watchdog, 35 base::MessageLoopProxy* io_message_loop, 36 base::WaitableEvent* shutdown_event) 37 : weak_factory_(this), 38 io_message_loop_(io_message_loop), 39 shutdown_event_(shutdown_event), 40 router_(router), 41 gpu_memory_manager_( 42 this, 43 GpuMemoryManager::kDefaultMaxSurfacesWithFrontbufferSoftLimit), 44 watchdog_(watchdog), 45 sync_point_manager_(new SyncPointManager) { 46 DCHECK(router_); 47 DCHECK(io_message_loop); 48 DCHECK(shutdown_event); 49 } 50 51 GpuChannelManager::~GpuChannelManager() { 52 gpu_channels_.clear(); 53 if (default_offscreen_surface_.get()) { 54 default_offscreen_surface_->Destroy(); 55 default_offscreen_surface_ = NULL; 56 } 57 DCHECK(image_operations_.empty()); 58 } 59 60 gpu::gles2::ProgramCache* GpuChannelManager::program_cache() { 61 if (!program_cache_.get() && 62 (gfx::g_driver_gl.ext.b_GL_ARB_get_program_binary || 63 gfx::g_driver_gl.ext.b_GL_OES_get_program_binary) && 64 !CommandLine::ForCurrentProcess()->HasSwitch( 65 switches::kDisableGpuProgramCache)) { 66 program_cache_.reset(new gpu::gles2::MemoryProgramCache()); 67 } 68 return program_cache_.get(); 69 } 70 71 gpu::gles2::ShaderTranslatorCache* 72 GpuChannelManager::shader_translator_cache() { 73 if (!shader_translator_cache_.get()) 74 shader_translator_cache_ = new gpu::gles2::ShaderTranslatorCache; 75 return shader_translator_cache_.get(); 76 } 77 78 void GpuChannelManager::RemoveChannel(int client_id) { 79 Send(new GpuHostMsg_DestroyChannel(client_id)); 80 gpu_channels_.erase(client_id); 81 } 82 83 int GpuChannelManager::GenerateRouteID() { 84 static int last_id = 0; 85 return ++last_id; 86 } 87 88 void GpuChannelManager::AddRoute(int32 routing_id, IPC::Listener* listener) { 89 router_->AddRoute(routing_id, listener); 90 } 91 92 void GpuChannelManager::RemoveRoute(int32 routing_id) { 93 router_->RemoveRoute(routing_id); 94 } 95 96 GpuChannel* GpuChannelManager::LookupChannel(int32 client_id) { 97 GpuChannelMap::const_iterator iter = gpu_channels_.find(client_id); 98 if (iter == gpu_channels_.end()) 99 return NULL; 100 else 101 return iter->second; 102 } 103 104 bool GpuChannelManager::OnMessageReceived(const IPC::Message& msg) { 105 bool handled = true; 106 IPC_BEGIN_MESSAGE_MAP(GpuChannelManager, msg) 107 IPC_MESSAGE_HANDLER(GpuMsg_EstablishChannel, OnEstablishChannel) 108 IPC_MESSAGE_HANDLER(GpuMsg_CloseChannel, OnCloseChannel) 109 IPC_MESSAGE_HANDLER(GpuMsg_CreateViewCommandBuffer, 110 OnCreateViewCommandBuffer) 111 IPC_MESSAGE_HANDLER(GpuMsg_CreateImage, OnCreateImage) 112 IPC_MESSAGE_HANDLER(GpuMsg_DeleteImage, OnDeleteImage) 113 IPC_MESSAGE_HANDLER(GpuMsg_CreateGpuMemoryBuffer, OnCreateGpuMemoryBuffer) 114 IPC_MESSAGE_HANDLER(GpuMsg_DestroyGpuMemoryBuffer, OnDestroyGpuMemoryBuffer) 115 IPC_MESSAGE_HANDLER(GpuMsg_LoadedShader, OnLoadedShader) 116 IPC_MESSAGE_UNHANDLED(handled = false) 117 IPC_END_MESSAGE_MAP() 118 return handled; 119 } 120 121 bool GpuChannelManager::Send(IPC::Message* msg) { return router_->Send(msg); } 122 123 void GpuChannelManager::OnEstablishChannel(int client_id, bool share_context) { 124 IPC::ChannelHandle channel_handle; 125 126 gfx::GLShareGroup* share_group = NULL; 127 gpu::gles2::MailboxManager* mailbox_manager = NULL; 128 if (share_context) { 129 if (!share_group_.get()) { 130 share_group_ = new gfx::GLShareGroup; 131 DCHECK(!mailbox_manager_.get()); 132 mailbox_manager_ = new gpu::gles2::MailboxManager; 133 } 134 share_group = share_group_.get(); 135 mailbox_manager = mailbox_manager_.get(); 136 } 137 138 scoped_ptr<GpuChannel> channel(new GpuChannel( 139 this, watchdog_, share_group, mailbox_manager, client_id, false)); 140 channel->Init(io_message_loop_.get(), shutdown_event_); 141 channel_handle.name = channel->GetChannelName(); 142 143 #if defined(OS_POSIX) 144 // On POSIX, pass the renderer-side FD. Also mark it as auto-close so 145 // that it gets closed after it has been sent. 146 int renderer_fd = channel->TakeRendererFileDescriptor(); 147 DCHECK_NE(-1, renderer_fd); 148 channel_handle.socket = base::FileDescriptor(renderer_fd, true); 149 #endif 150 151 gpu_channels_.set(client_id, channel.Pass()); 152 153 Send(new GpuHostMsg_ChannelEstablished(channel_handle)); 154 } 155 156 void GpuChannelManager::OnCloseChannel( 157 const IPC::ChannelHandle& channel_handle) { 158 for (GpuChannelMap::iterator iter = gpu_channels_.begin(); 159 iter != gpu_channels_.end(); ++iter) { 160 if (iter->second->GetChannelName() == channel_handle.name) { 161 gpu_channels_.erase(iter); 162 return; 163 } 164 } 165 } 166 167 void GpuChannelManager::OnCreateViewCommandBuffer( 168 const gfx::GLSurfaceHandle& window, 169 int32 surface_id, 170 int32 client_id, 171 const GPUCreateCommandBufferConfig& init_params, 172 int32 route_id) { 173 DCHECK(surface_id); 174 CreateCommandBufferResult result = CREATE_COMMAND_BUFFER_FAILED; 175 176 GpuChannelMap::const_iterator iter = gpu_channels_.find(client_id); 177 if (iter != gpu_channels_.end()) { 178 result = iter->second->CreateViewCommandBuffer( 179 window, surface_id, init_params, route_id); 180 } 181 182 Send(new GpuHostMsg_CommandBufferCreated(result)); 183 } 184 185 void GpuChannelManager::CreateImage( 186 gfx::PluginWindowHandle window, int32 client_id, int32 image_id) { 187 gfx::Size size; 188 189 GpuChannelMap::const_iterator iter = gpu_channels_.find(client_id); 190 if (iter != gpu_channels_.end()) { 191 iter->second->CreateImage(window, image_id, &size); 192 } 193 194 Send(new GpuHostMsg_ImageCreated(size)); 195 } 196 197 void GpuChannelManager::OnCreateImage( 198 gfx::PluginWindowHandle window, int32 client_id, int32 image_id) { 199 DCHECK(image_id); 200 201 if (image_operations_.empty()) { 202 CreateImage(window, client_id, image_id); 203 } else { 204 image_operations_.push_back( 205 new ImageOperation(0, base::Bind(&GpuChannelManager::CreateImage, 206 base::Unretained(this), 207 window, 208 client_id, 209 image_id))); 210 } 211 } 212 213 void GpuChannelManager::DeleteImage(int32 client_id, int32 image_id) { 214 GpuChannelMap::const_iterator iter = gpu_channels_.find(client_id); 215 if (iter != gpu_channels_.end()) { 216 iter->second->DeleteImage(image_id); 217 } 218 } 219 220 void GpuChannelManager::OnDeleteImage( 221 int32 client_id, int32 image_id, int32 sync_point) { 222 DCHECK(image_id); 223 224 if (!sync_point && image_operations_.empty()) { 225 DeleteImage(client_id, image_id); 226 } else { 227 image_operations_.push_back( 228 new ImageOperation(sync_point, 229 base::Bind(&GpuChannelManager::DeleteImage, 230 base::Unretained(this), 231 client_id, 232 image_id))); 233 if (sync_point) { 234 sync_point_manager()->AddSyncPointCallback( 235 sync_point, 236 base::Bind(&GpuChannelManager::OnDeleteImageSyncPointRetired, 237 base::Unretained(this), 238 image_operations_.back())); 239 } 240 } 241 } 242 243 void GpuChannelManager::OnDeleteImageSyncPointRetired( 244 ImageOperation* image_operation) { 245 // Mark operation as no longer having a pending sync point. 246 image_operation->sync_point = 0; 247 248 // De-queue operations until we reach a pending sync point. 249 while (!image_operations_.empty()) { 250 // Check if operation has a pending sync point. 251 if (image_operations_.front()->sync_point) 252 return; 253 254 image_operations_.front()->callback.Run(); 255 delete image_operations_.front(); 256 image_operations_.pop_front(); 257 } 258 } 259 260 void GpuChannelManager::OnCreateGpuMemoryBuffer( 261 const gfx::GpuMemoryBufferHandle& handle, 262 const gfx::Size& size, 263 unsigned internalformat, 264 unsigned usage) { 265 Send(new GpuHostMsg_GpuMemoryBufferCreated(gfx::GpuMemoryBufferHandle())); 266 } 267 268 void GpuChannelManager::OnDestroyGpuMemoryBuffer( 269 const gfx::GpuMemoryBufferHandle& handle, 270 int32 sync_point) { 271 } 272 273 void GpuChannelManager::OnLoadedShader(std::string program_proto) { 274 if (program_cache()) 275 program_cache()->LoadProgram(program_proto); 276 } 277 278 bool GpuChannelManager::HandleMessagesScheduled() { 279 for (GpuChannelMap::iterator iter = gpu_channels_.begin(); 280 iter != gpu_channels_.end(); ++iter) { 281 if (iter->second->handle_messages_scheduled()) 282 return true; 283 } 284 return false; 285 } 286 287 uint64 GpuChannelManager::MessagesProcessed() { 288 uint64 messages_processed = 0; 289 290 for (GpuChannelMap::iterator iter = gpu_channels_.begin(); 291 iter != gpu_channels_.end(); ++iter) { 292 messages_processed += iter->second->messages_processed(); 293 } 294 return messages_processed; 295 } 296 297 void GpuChannelManager::LoseAllContexts() { 298 for (GpuChannelMap::iterator iter = gpu_channels_.begin(); 299 iter != gpu_channels_.end(); ++iter) { 300 iter->second->MarkAllContextsLost(); 301 } 302 base::MessageLoop::current()->PostTask( 303 FROM_HERE, 304 base::Bind(&GpuChannelManager::OnLoseAllContexts, 305 weak_factory_.GetWeakPtr())); 306 } 307 308 void GpuChannelManager::OnLoseAllContexts() { 309 gpu_channels_.clear(); 310 } 311 312 gfx::GLSurface* GpuChannelManager::GetDefaultOffscreenSurface() { 313 if (!default_offscreen_surface_.get()) { 314 default_offscreen_surface_ = 315 gfx::GLSurface::CreateOffscreenGLSurface(gfx::Size()); 316 } 317 return default_offscreen_surface_.get(); 318 } 319 320 } // namespace content 321