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_impl.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"
27 #if defined(USE_OZONE)
28 #include "ui/ozone/public/gpu_platform_support.h"
29 #include "ui/ozone/public/ozone_platform.h"
36 class GpuChannelManagerMessageFilter
: public IPC::MessageFilter
{
38 GpuChannelManagerMessageFilter(
39 GpuMemoryBufferFactory
* gpu_memory_buffer_factory
)
40 : sender_(NULL
), gpu_memory_buffer_factory_(gpu_memory_buffer_factory
) {}
42 void OnFilterAdded(IPC::Sender
* sender
) override
{
47 void OnFilterRemoved() override
{
52 bool OnMessageReceived(const IPC::Message
& message
) override
{
55 IPC_BEGIN_MESSAGE_MAP(GpuChannelManagerMessageFilter
, message
)
56 IPC_MESSAGE_HANDLER(GpuMsg_CreateGpuMemoryBuffer
, OnCreateGpuMemoryBuffer
)
57 IPC_MESSAGE_UNHANDLED(handled
= false)
63 ~GpuChannelManagerMessageFilter() override
{}
65 // GPU IO thread bounces off GpuMsg_CreateGpuMemoryBuffer message, because
66 // the UI thread in the browser process must remain fast at all times.
67 void OnCreateGpuMemoryBuffer(
68 const GpuMsg_CreateGpuMemoryBuffer_Params
& params
) {
70 "GpuChannelManagerMessageFilter::OnCreateGpuMemoryBuffer",
71 "id", params
.id
, "client_id", params
.client_id
);
72 sender_
->Send(new GpuHostMsg_GpuMemoryBufferCreated(
73 gpu_memory_buffer_factory_
->CreateGpuMemoryBuffer(
74 params
.id
, params
.size
, params
.format
, params
.usage
,
75 params
.client_id
, params
.surface_handle
)));
79 GpuMemoryBufferFactory
* gpu_memory_buffer_factory_
;
82 gfx::GpuMemoryBufferType
GetGpuMemoryBufferFactoryType() {
83 std::vector
<gfx::GpuMemoryBufferType
> supported_types
;
84 GpuMemoryBufferFactory::GetSupportedTypes(&supported_types
);
85 DCHECK(!supported_types
.empty());
86 return supported_types
[0];
91 GpuChannelManager::GpuChannelManager(
92 MessageRouter
* router
,
93 GpuWatchdog
* watchdog
,
94 base::SingleThreadTaskRunner
* io_task_runner
,
95 base::WaitableEvent
* shutdown_event
,
96 IPC::SyncChannel
* channel
)
97 : io_task_runner_(io_task_runner
),
98 shutdown_event_(shutdown_event
),
102 GpuMemoryManager::kDefaultMaxSurfacesWithFrontbufferSoftLimit
),
104 sync_point_manager_(gpu::SyncPointManager::Create(false)),
105 gpu_memory_buffer_factory_(
106 GpuMemoryBufferFactory::Create(GetGpuMemoryBufferFactoryType())),
109 new GpuChannelManagerMessageFilter(gpu_memory_buffer_factory_
.get())),
110 relinquish_resources_pending_(false),
111 weak_factory_(this) {
113 DCHECK(io_task_runner
);
114 DCHECK(shutdown_event
);
115 channel_
->AddFilter(filter_
.get());
118 GpuChannelManager::~GpuChannelManager() {
119 gpu_channels_
.clear();
120 if (default_offscreen_surface_
.get()) {
121 default_offscreen_surface_
->Destroy();
122 default_offscreen_surface_
= NULL
;
126 gpu::gles2::ProgramCache
* GpuChannelManager::program_cache() {
127 if (!program_cache_
.get() &&
128 (gfx::g_driver_gl
.ext
.b_GL_ARB_get_program_binary
||
129 gfx::g_driver_gl
.ext
.b_GL_OES_get_program_binary
) &&
130 !base::CommandLine::ForCurrentProcess()->HasSwitch(
131 switches::kDisableGpuProgramCache
)) {
132 program_cache_
.reset(new gpu::gles2::MemoryProgramCache());
134 return program_cache_
.get();
137 gpu::gles2::ShaderTranslatorCache
*
138 GpuChannelManager::shader_translator_cache() {
139 if (!shader_translator_cache_
.get())
140 shader_translator_cache_
= new gpu::gles2::ShaderTranslatorCache
;
141 return shader_translator_cache_
.get();
144 void GpuChannelManager::RemoveChannel(int client_id
) {
145 Send(new GpuHostMsg_DestroyChannel(client_id
));
146 gpu_channels_
.erase(client_id
);
147 CheckRelinquishGpuResources();
150 int GpuChannelManager::GenerateRouteID() {
151 static int last_id
= 0;
155 void GpuChannelManager::AddRoute(int32 routing_id
, IPC::Listener
* listener
) {
156 router_
->AddRoute(routing_id
, listener
);
159 void GpuChannelManager::RemoveRoute(int32 routing_id
) {
160 router_
->RemoveRoute(routing_id
);
163 GpuChannel
* GpuChannelManager::LookupChannel(int32 client_id
) {
164 GpuChannelMap::const_iterator iter
= gpu_channels_
.find(client_id
);
165 if (iter
== gpu_channels_
.end())
171 bool GpuChannelManager::OnMessageReceived(const IPC::Message
& msg
) {
173 IPC_BEGIN_MESSAGE_MAP(GpuChannelManager
, msg
)
174 IPC_MESSAGE_HANDLER(GpuMsg_EstablishChannel
, OnEstablishChannel
)
175 IPC_MESSAGE_HANDLER(GpuMsg_CloseChannel
, OnCloseChannel
)
176 IPC_MESSAGE_HANDLER(GpuMsg_CreateViewCommandBuffer
,
177 OnCreateViewCommandBuffer
)
178 IPC_MESSAGE_HANDLER(GpuMsg_DestroyGpuMemoryBuffer
, OnDestroyGpuMemoryBuffer
)
179 IPC_MESSAGE_HANDLER(GpuMsg_LoadedShader
, OnLoadedShader
)
180 IPC_MESSAGE_HANDLER(GpuMsg_RelinquishResources
, OnRelinquishResources
)
181 IPC_MESSAGE_HANDLER(GpuMsg_UpdateValueState
, OnUpdateValueState
)
182 IPC_MESSAGE_UNHANDLED(handled
= false)
183 IPC_END_MESSAGE_MAP()
187 bool GpuChannelManager::Send(IPC::Message
* msg
) { return router_
->Send(msg
); }
189 void GpuChannelManager::OnEstablishChannel(int client_id
,
191 bool allow_future_sync_points
) {
192 IPC::ChannelHandle channel_handle
;
194 gfx::GLShareGroup
* share_group
= NULL
;
195 gpu::gles2::MailboxManager
* mailbox_manager
= NULL
;
197 if (!share_group_
.get()) {
198 share_group_
= new gfx::GLShareGroup
;
199 DCHECK(!mailbox_manager_
.get());
200 mailbox_manager_
= new gpu::gles2::MailboxManagerImpl
;
202 share_group
= share_group_
.get();
203 mailbox_manager
= mailbox_manager_
.get();
206 scoped_ptr
<GpuChannel
> channel(new GpuChannel(this,
212 allow_future_sync_points
));
213 channel
->Init(io_task_runner_
.get(), shutdown_event_
);
214 channel_handle
.name
= channel
->GetChannelName();
216 #if defined(OS_POSIX)
217 // On POSIX, pass the renderer-side FD. Also mark it as auto-close so
218 // that it gets closed after it has been sent.
219 base::ScopedFD renderer_fd
= channel
->TakeRendererFileDescriptor();
220 DCHECK(renderer_fd
.is_valid());
221 channel_handle
.socket
= base::FileDescriptor(renderer_fd
.Pass());
224 gpu_channels_
.set(client_id
, channel
.Pass());
226 Send(new GpuHostMsg_ChannelEstablished(channel_handle
));
229 void GpuChannelManager::OnCloseChannel(
230 const IPC::ChannelHandle
& channel_handle
) {
231 for (GpuChannelMap::iterator iter
= gpu_channels_
.begin();
232 iter
!= gpu_channels_
.end(); ++iter
) {
233 if (iter
->second
->GetChannelName() == channel_handle
.name
) {
234 gpu_channels_
.erase(iter
);
235 CheckRelinquishGpuResources();
241 void GpuChannelManager::OnCreateViewCommandBuffer(
242 const gfx::GLSurfaceHandle
& window
,
245 const GPUCreateCommandBufferConfig
& init_params
,
248 CreateCommandBufferResult result
= CREATE_COMMAND_BUFFER_FAILED
;
250 GpuChannelMap::const_iterator iter
= gpu_channels_
.find(client_id
);
251 if (iter
!= gpu_channels_
.end()) {
252 result
= iter
->second
->CreateViewCommandBuffer(
253 window
, surface_id
, init_params
, route_id
);
256 Send(new GpuHostMsg_CommandBufferCreated(result
));
259 void GpuChannelManager::DestroyGpuMemoryBuffer(
260 gfx::GpuMemoryBufferId id
,
262 io_task_runner_
->PostTask(
263 FROM_HERE
, base::Bind(&GpuChannelManager::DestroyGpuMemoryBufferOnIO
,
264 base::Unretained(this), id
, client_id
));
267 void GpuChannelManager::DestroyGpuMemoryBufferOnIO(
268 gfx::GpuMemoryBufferId id
,
270 gpu_memory_buffer_factory_
->DestroyGpuMemoryBuffer(id
, client_id
);
273 void GpuChannelManager::OnDestroyGpuMemoryBuffer(
274 gfx::GpuMemoryBufferId id
,
278 DestroyGpuMemoryBuffer(id
, client_id
);
280 sync_point_manager()->AddSyncPointCallback(
282 base::Bind(&GpuChannelManager::DestroyGpuMemoryBuffer
,
283 base::Unretained(this),
289 void GpuChannelManager::OnUpdateValueState(
290 int client_id
, unsigned int target
, const gpu::ValueState
& state
) {
291 // Only pass updated state to the channel corresponding to the
292 // render_widget_host where the event originated.
293 GpuChannelMap::const_iterator iter
= gpu_channels_
.find(client_id
);
294 if (iter
!= gpu_channels_
.end()) {
295 iter
->second
->HandleUpdateValueState(target
, state
);
299 void GpuChannelManager::OnLoadedShader(std::string program_proto
) {
301 program_cache()->LoadProgram(program_proto
);
304 bool GpuChannelManager::HandleMessagesScheduled() {
305 for (GpuChannelMap::iterator iter
= gpu_channels_
.begin();
306 iter
!= gpu_channels_
.end(); ++iter
) {
307 if (iter
->second
->handle_messages_scheduled())
313 uint64
GpuChannelManager::MessagesProcessed() {
314 uint64 messages_processed
= 0;
316 for (GpuChannelMap::iterator iter
= gpu_channels_
.begin();
317 iter
!= gpu_channels_
.end(); ++iter
) {
318 messages_processed
+= iter
->second
->messages_processed();
320 return messages_processed
;
323 void GpuChannelManager::LoseAllContexts() {
324 for (GpuChannelMap::iterator iter
= gpu_channels_
.begin();
325 iter
!= gpu_channels_
.end(); ++iter
) {
326 iter
->second
->MarkAllContextsLost();
328 base::ThreadTaskRunnerHandle::Get()->PostTask(
329 FROM_HERE
, base::Bind(&GpuChannelManager::OnLoseAllContexts
,
330 weak_factory_
.GetWeakPtr()));
333 void GpuChannelManager::OnLoseAllContexts() {
334 gpu_channels_
.clear();
335 CheckRelinquishGpuResources();
338 gfx::GLSurface
* GpuChannelManager::GetDefaultOffscreenSurface() {
339 if (!default_offscreen_surface_
.get()) {
340 default_offscreen_surface_
=
341 gfx::GLSurface::CreateOffscreenGLSurface(gfx::Size());
343 return default_offscreen_surface_
.get();
346 void GpuChannelManager::OnRelinquishResources() {
347 relinquish_resources_pending_
= true;
348 CheckRelinquishGpuResources();
351 void GpuChannelManager::CheckRelinquishGpuResources() {
352 if (relinquish_resources_pending_
&& gpu_channels_
.size() <= 1) {
353 relinquish_resources_pending_
= false;
354 if (default_offscreen_surface_
.get()) {
355 default_offscreen_surface_
->DestroyAndTerminateDisplay();
356 default_offscreen_surface_
= NULL
;
358 #if defined(USE_OZONE)
359 ui::OzonePlatform::GetInstance()
360 ->GetGpuPlatformSupport()
361 ->RelinquishGpuResources(
362 base::Bind(&GpuChannelManager::OnResourcesRelinquished
,
363 weak_factory_
.GetWeakPtr()));
365 OnResourcesRelinquished();
370 void GpuChannelManager::OnResourcesRelinquished() {
371 Send(new GpuHostMsg_ResourcesRelinquished());
374 } // namespace content