• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
ImageOperation(int32 sync_point,base::Closure callback)24 GpuChannelManager::ImageOperation::ImageOperation(
25     int32 sync_point, base::Closure callback)
26     : sync_point(sync_point),
27       callback(callback) {
28 }
29 
~ImageOperation()30 GpuChannelManager::ImageOperation::~ImageOperation() {
31 }
32 
GpuChannelManager(MessageRouter * router,GpuWatchdog * watchdog,base::MessageLoopProxy * io_message_loop,base::WaitableEvent * shutdown_event)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 
~GpuChannelManager()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 
program_cache()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*
shader_translator_cache()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 
RemoveChannel(int client_id)78 void GpuChannelManager::RemoveChannel(int client_id) {
79   Send(new GpuHostMsg_DestroyChannel(client_id));
80   gpu_channels_.erase(client_id);
81 }
82 
GenerateRouteID()83 int GpuChannelManager::GenerateRouteID() {
84   static int last_id = 0;
85   return ++last_id;
86 }
87 
AddRoute(int32 routing_id,IPC::Listener * listener)88 void GpuChannelManager::AddRoute(int32 routing_id, IPC::Listener* listener) {
89   router_->AddRoute(routing_id, listener);
90 }
91 
RemoveRoute(int32 routing_id)92 void GpuChannelManager::RemoveRoute(int32 routing_id) {
93   router_->RemoveRoute(routing_id);
94 }
95 
LookupChannel(int32 client_id)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 
OnMessageReceived(const IPC::Message & msg)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 
Send(IPC::Message * msg)121 bool GpuChannelManager::Send(IPC::Message* msg) { return router_->Send(msg); }
122 
OnEstablishChannel(int client_id,bool share_context)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 
OnCloseChannel(const IPC::ChannelHandle & channel_handle)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 
OnCreateViewCommandBuffer(const gfx::GLSurfaceHandle & window,int32 surface_id,int32 client_id,const GPUCreateCommandBufferConfig & init_params,int32 route_id)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 
CreateImage(gfx::PluginWindowHandle window,int32 client_id,int32 image_id)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 
OnCreateImage(gfx::PluginWindowHandle window,int32 client_id,int32 image_id)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 
DeleteImage(int32 client_id,int32 image_id)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 
OnDeleteImage(int32 client_id,int32 image_id,int32 sync_point)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 
OnDeleteImageSyncPointRetired(ImageOperation * image_operation)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 
OnCreateGpuMemoryBuffer(const gfx::GpuMemoryBufferHandle & handle,const gfx::Size & size,unsigned internalformat,unsigned usage)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 
OnDestroyGpuMemoryBuffer(const gfx::GpuMemoryBufferHandle & handle,int32 sync_point)268 void GpuChannelManager::OnDestroyGpuMemoryBuffer(
269     const gfx::GpuMemoryBufferHandle& handle,
270     int32 sync_point) {
271 }
272 
OnLoadedShader(std::string program_proto)273 void GpuChannelManager::OnLoadedShader(std::string program_proto) {
274   if (program_cache())
275     program_cache()->LoadProgram(program_proto);
276 }
277 
HandleMessagesScheduled()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 
MessagesProcessed()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 
LoseAllContexts()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 
OnLoseAllContexts()308 void GpuChannelManager::OnLoseAllContexts() {
309   gpu_channels_.clear();
310 }
311 
GetDefaultOffscreenSurface()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