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 "base/location.h"
10 #include "base/single_thread_task_runner.h"
11 #include "base/thread_task_runner_handle.h"
12 #include "content/common/gpu/gpu_channel.h"
13 #include "content/common/gpu/gpu_memory_buffer_factory.h"
14 #include "content/common/gpu/gpu_memory_manager.h"
15 #include "content/common/gpu/gpu_messages.h"
16 #include "content/common/message_router.h"
17 #include "gpu/command_buffer/common/value_state.h"
18 #include "gpu/command_buffer/service/feature_info.h"
19 #include "gpu/command_buffer/service/gpu_switches.h"
20 #include "gpu/command_buffer/service/mailbox_manager.h"
21 #include "gpu/command_buffer/service/memory_program_cache.h"
22 #include "gpu/command_buffer/service/shader_translator_cache.h"
23 #include "gpu/command_buffer/service/sync_point_manager.h"
24 #include "ipc/message_filter.h"
25 #include "ui/gl/gl_bindings.h"
26 #include "ui/gl/gl_share_group.h"
30 GpuChannelManager::GpuChannelManager(
31 MessageRouter
* router
,
32 GpuWatchdog
* watchdog
,
33 base::SingleThreadTaskRunner
* io_task_runner
,
34 base::WaitableEvent
* shutdown_event
,
35 IPC::SyncChannel
* channel
,
36 IPC::AttachmentBroker
* broker
,
37 gpu::SyncPointManager
* sync_point_manager
,
38 GpuMemoryBufferFactory
* gpu_memory_buffer_factory
)
39 : io_task_runner_(io_task_runner
),
40 shutdown_event_(shutdown_event
),
44 GpuMemoryManager::kDefaultMaxSurfacesWithFrontbufferSoftLimit
),
46 sync_point_manager_(sync_point_manager
),
47 gpu_memory_buffer_factory_(gpu_memory_buffer_factory
),
49 attachment_broker_(broker
),
52 DCHECK(io_task_runner
);
53 DCHECK(shutdown_event
);
56 GpuChannelManager::~GpuChannelManager() {
57 gpu_channels_
.clear();
58 if (default_offscreen_surface_
.get()) {
59 default_offscreen_surface_
->Destroy();
60 default_offscreen_surface_
= NULL
;
64 gpu::gles2::ProgramCache
* GpuChannelManager::program_cache() {
65 if (!program_cache_
.get() &&
66 (gfx::g_driver_gl
.ext
.b_GL_ARB_get_program_binary
||
67 gfx::g_driver_gl
.ext
.b_GL_OES_get_program_binary
) &&
68 !base::CommandLine::ForCurrentProcess()->HasSwitch(
69 switches::kDisableGpuProgramCache
)) {
70 program_cache_
.reset(new gpu::gles2::MemoryProgramCache());
72 return program_cache_
.get();
75 gpu::gles2::ShaderTranslatorCache
*
76 GpuChannelManager::shader_translator_cache() {
77 if (!shader_translator_cache_
.get())
78 shader_translator_cache_
= new gpu::gles2::ShaderTranslatorCache
;
79 return shader_translator_cache_
.get();
82 void GpuChannelManager::RemoveChannel(int client_id
) {
83 Send(new GpuHostMsg_DestroyChannel(client_id
));
84 gpu_channels_
.erase(client_id
);
87 int GpuChannelManager::GenerateRouteID() {
88 static int last_id
= 0;
92 void GpuChannelManager::AddRoute(int32 routing_id
, IPC::Listener
* listener
) {
93 router_
->AddRoute(routing_id
, listener
);
96 void GpuChannelManager::RemoveRoute(int32 routing_id
) {
97 router_
->RemoveRoute(routing_id
);
100 GpuChannel
* GpuChannelManager::LookupChannel(int32 client_id
) {
101 GpuChannelMap::const_iterator iter
= gpu_channels_
.find(client_id
);
102 if (iter
== gpu_channels_
.end())
108 bool GpuChannelManager::OnMessageReceived(const IPC::Message
& msg
) {
110 IPC_BEGIN_MESSAGE_MAP(GpuChannelManager
, msg
)
111 IPC_MESSAGE_HANDLER(GpuMsg_EstablishChannel
, OnEstablishChannel
)
112 IPC_MESSAGE_HANDLER(GpuMsg_CloseChannel
, OnCloseChannel
)
113 IPC_MESSAGE_HANDLER(GpuMsg_CreateViewCommandBuffer
,
114 OnCreateViewCommandBuffer
)
115 IPC_MESSAGE_HANDLER(GpuMsg_DestroyGpuMemoryBuffer
, OnDestroyGpuMemoryBuffer
)
116 IPC_MESSAGE_HANDLER(GpuMsg_LoadedShader
, OnLoadedShader
)
117 IPC_MESSAGE_HANDLER(GpuMsg_Finalize
, OnFinalize
)
118 IPC_MESSAGE_HANDLER(GpuMsg_UpdateValueState
, OnUpdateValueState
)
119 IPC_MESSAGE_UNHANDLED(handled
= false)
120 IPC_END_MESSAGE_MAP()
124 bool GpuChannelManager::Send(IPC::Message
* msg
) { return router_
->Send(msg
); }
126 void GpuChannelManager::OnEstablishChannel(int client_id
,
127 uint64_t client_tracing_id
,
129 bool allow_future_sync_points
) {
130 IPC::ChannelHandle channel_handle
;
132 gfx::GLShareGroup
* share_group
= NULL
;
133 gpu::gles2::MailboxManager
* mailbox_manager
= NULL
;
135 if (!share_group_
.get()) {
136 share_group_
= new gfx::GLShareGroup
;
137 DCHECK(!mailbox_manager_
.get());
138 mailbox_manager_
= gpu::gles2::MailboxManager::Create();
140 share_group
= share_group_
.get();
141 mailbox_manager
= mailbox_manager_
.get();
144 scoped_ptr
<GpuChannel
> channel(new GpuChannel(this,
151 allow_future_sync_points
));
152 channel
->Init(io_task_runner_
.get(), shutdown_event_
, attachment_broker_
);
153 channel_handle
.name
= channel
->GetChannelName();
155 #if defined(OS_POSIX)
156 // On POSIX, pass the renderer-side FD. Also mark it as auto-close so
157 // that it gets closed after it has been sent.
158 base::ScopedFD renderer_fd
= channel
->TakeRendererFileDescriptor();
159 DCHECK(renderer_fd
.is_valid());
160 channel_handle
.socket
= base::FileDescriptor(renderer_fd
.Pass());
163 gpu_channels_
.set(client_id
, channel
.Pass());
165 Send(new GpuHostMsg_ChannelEstablished(channel_handle
));
168 void GpuChannelManager::OnCloseChannel(
169 const IPC::ChannelHandle
& channel_handle
) {
170 for (GpuChannelMap::iterator iter
= gpu_channels_
.begin();
171 iter
!= gpu_channels_
.end(); ++iter
) {
172 if (iter
->second
->GetChannelName() == channel_handle
.name
) {
173 gpu_channels_
.erase(iter
);
179 void GpuChannelManager::OnCreateViewCommandBuffer(
180 const gfx::GLSurfaceHandle
& window
,
183 const GPUCreateCommandBufferConfig
& init_params
,
186 CreateCommandBufferResult result
= CREATE_COMMAND_BUFFER_FAILED
;
188 GpuChannelMap::const_iterator iter
= gpu_channels_
.find(client_id
);
189 if (iter
!= gpu_channels_
.end()) {
190 result
= iter
->second
->CreateViewCommandBuffer(
191 window
, surface_id
, init_params
, route_id
);
194 Send(new GpuHostMsg_CommandBufferCreated(result
));
197 void GpuChannelManager::DestroyGpuMemoryBuffer(
198 gfx::GpuMemoryBufferId id
,
200 io_task_runner_
->PostTask(
201 FROM_HERE
, base::Bind(&GpuChannelManager::DestroyGpuMemoryBufferOnIO
,
202 base::Unretained(this), id
, client_id
));
205 void GpuChannelManager::DestroyGpuMemoryBufferOnIO(
206 gfx::GpuMemoryBufferId id
,
208 gpu_memory_buffer_factory_
->DestroyGpuMemoryBuffer(id
, client_id
);
211 void GpuChannelManager::OnDestroyGpuMemoryBuffer(
212 gfx::GpuMemoryBufferId id
,
216 DestroyGpuMemoryBuffer(id
, client_id
);
218 sync_point_manager()->AddSyncPointCallback(
220 base::Bind(&GpuChannelManager::DestroyGpuMemoryBuffer
,
221 base::Unretained(this),
227 void GpuChannelManager::OnUpdateValueState(
228 int client_id
, unsigned int target
, const gpu::ValueState
& state
) {
229 // Only pass updated state to the channel corresponding to the
230 // render_widget_host where the event originated.
231 GpuChannelMap::const_iterator iter
= gpu_channels_
.find(client_id
);
232 if (iter
!= gpu_channels_
.end()) {
233 iter
->second
->HandleUpdateValueState(target
, state
);
237 void GpuChannelManager::OnLoadedShader(std::string program_proto
) {
239 program_cache()->LoadProgram(program_proto
);
242 bool GpuChannelManager::HandleMessagesScheduled() {
243 for (GpuChannelMap::iterator iter
= gpu_channels_
.begin();
244 iter
!= gpu_channels_
.end(); ++iter
) {
245 if (iter
->second
->handle_messages_scheduled())
251 uint64
GpuChannelManager::MessagesProcessed() {
252 uint64 messages_processed
= 0;
254 for (GpuChannelMap::iterator iter
= gpu_channels_
.begin();
255 iter
!= gpu_channels_
.end(); ++iter
) {
256 messages_processed
+= iter
->second
->messages_processed();
258 return messages_processed
;
261 void GpuChannelManager::LoseAllContexts() {
262 for (GpuChannelMap::iterator iter
= gpu_channels_
.begin();
263 iter
!= gpu_channels_
.end(); ++iter
) {
264 iter
->second
->MarkAllContextsLost();
266 base::ThreadTaskRunnerHandle::Get()->PostTask(
267 FROM_HERE
, base::Bind(&GpuChannelManager::OnLoseAllContexts
,
268 weak_factory_
.GetWeakPtr()));
271 void GpuChannelManager::OnLoseAllContexts() {
272 gpu_channels_
.clear();
275 gfx::GLSurface
* GpuChannelManager::GetDefaultOffscreenSurface() {
276 if (!default_offscreen_surface_
.get()) {
277 default_offscreen_surface_
=
278 gfx::GLSurface::CreateOffscreenGLSurface(gfx::Size());
280 return default_offscreen_surface_
.get();
283 void GpuChannelManager::OnFinalize() {
284 // Quit the GPU process
285 base::MessageLoop::current()->Quit();
288 } // namespace content