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/child/child_thread.h"
10 #include "content/common/gpu/gpu_channel.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 "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 "ui/gl/gl_bindings.h"
19 #include "ui/gl/gl_share_group.h"
23 GpuChannelManager::ImageOperation::ImageOperation(
24 int32 sync_point
, base::Closure callback
)
25 : sync_point(sync_point
),
29 GpuChannelManager::ImageOperation::~ImageOperation() {
32 GpuChannelManager::GpuChannelManager(ChildThread
* gpu_child_thread
,
33 GpuWatchdog
* watchdog
,
34 base::MessageLoopProxy
* io_message_loop
,
35 base::WaitableEvent
* shutdown_event
)
36 : weak_factory_(this),
37 io_message_loop_(io_message_loop
),
38 shutdown_event_(shutdown_event
),
39 gpu_child_thread_(gpu_child_thread
),
42 GpuMemoryManager::kDefaultMaxSurfacesWithFrontbufferSoftLimit
),
44 sync_point_manager_(new SyncPointManager
) {
45 DCHECK(gpu_child_thread
);
46 DCHECK(io_message_loop
);
47 DCHECK(shutdown_event
);
50 GpuChannelManager::~GpuChannelManager() {
51 gpu_channels_
.clear();
52 if (default_offscreen_surface_
.get()) {
53 default_offscreen_surface_
->Destroy();
54 default_offscreen_surface_
= NULL
;
56 DCHECK(image_operations_
.empty());
59 gpu::gles2::ProgramCache
* GpuChannelManager::program_cache() {
60 if (!program_cache_
.get() &&
61 (gfx::g_driver_gl
.ext
.b_ARB_get_program_binary
||
62 gfx::g_driver_gl
.ext
.b_OES_get_program_binary
) &&
63 !CommandLine::ForCurrentProcess()->HasSwitch(
64 switches::kDisableGpuProgramCache
)) {
65 program_cache_
.reset(new gpu::gles2::MemoryProgramCache());
67 return program_cache_
.get();
70 void GpuChannelManager::RemoveChannel(int client_id
) {
71 Send(new GpuHostMsg_DestroyChannel(client_id
));
72 gpu_channels_
.erase(client_id
);
75 int GpuChannelManager::GenerateRouteID() {
76 static int last_id
= 0;
80 void GpuChannelManager::AddRoute(int32 routing_id
, IPC::Listener
* listener
) {
81 gpu_child_thread_
->AddRoute(routing_id
, listener
);
84 void GpuChannelManager::RemoveRoute(int32 routing_id
) {
85 gpu_child_thread_
->RemoveRoute(routing_id
);
88 GpuChannel
* GpuChannelManager::LookupChannel(int32 client_id
) {
89 GpuChannelMap::const_iterator iter
= gpu_channels_
.find(client_id
);
90 if (iter
== gpu_channels_
.end())
93 return iter
->second
.get();
96 bool GpuChannelManager::OnMessageReceived(const IPC::Message
& msg
) {
97 bool msg_is_ok
= true;
99 IPC_BEGIN_MESSAGE_MAP_EX(GpuChannelManager
, msg
, msg_is_ok
)
100 IPC_MESSAGE_HANDLER(GpuMsg_EstablishChannel
, OnEstablishChannel
)
101 IPC_MESSAGE_HANDLER(GpuMsg_CloseChannel
, OnCloseChannel
)
102 IPC_MESSAGE_HANDLER(GpuMsg_CreateViewCommandBuffer
,
103 OnCreateViewCommandBuffer
)
104 IPC_MESSAGE_HANDLER(GpuMsg_CreateImage
, OnCreateImage
)
105 IPC_MESSAGE_HANDLER(GpuMsg_DeleteImage
, OnDeleteImage
)
106 IPC_MESSAGE_HANDLER(GpuMsg_LoadedShader
, OnLoadedShader
)
107 IPC_MESSAGE_UNHANDLED(handled
= false)
108 IPC_END_MESSAGE_MAP_EX()
112 bool GpuChannelManager::Send(IPC::Message
* msg
) {
113 return gpu_child_thread_
->Send(msg
);
116 void GpuChannelManager::OnEstablishChannel(int client_id
, bool share_context
) {
117 IPC::ChannelHandle channel_handle
;
119 gfx::GLShareGroup
* share_group
= NULL
;
120 gpu::gles2::MailboxManager
* mailbox_manager
= NULL
;
122 if (!share_group_
.get()) {
123 share_group_
= new gfx::GLShareGroup
;
124 DCHECK(!mailbox_manager_
.get());
125 mailbox_manager_
= new gpu::gles2::MailboxManager
;
127 share_group
= share_group_
.get();
128 mailbox_manager
= mailbox_manager_
.get();
131 scoped_refptr
<GpuChannel
> channel
= new GpuChannel(this,
137 if (channel
->Init(io_message_loop_
.get(), shutdown_event_
)) {
138 gpu_channels_
[client_id
] = channel
;
139 channel_handle
.name
= channel
->GetChannelName();
141 #if defined(OS_POSIX)
142 // On POSIX, pass the renderer-side FD. Also mark it as auto-close so
143 // that it gets closed after it has been sent.
144 int renderer_fd
= channel
->TakeRendererFileDescriptor();
145 DCHECK_NE(-1, renderer_fd
);
146 channel_handle
.socket
= base::FileDescriptor(renderer_fd
, true);
150 Send(new GpuHostMsg_ChannelEstablished(channel_handle
));
153 void GpuChannelManager::OnCloseChannel(
154 const IPC::ChannelHandle
& channel_handle
) {
155 for (GpuChannelMap::iterator iter
= gpu_channels_
.begin();
156 iter
!= gpu_channels_
.end(); ++iter
) {
157 if (iter
->second
->GetChannelName() == channel_handle
.name
) {
158 gpu_channels_
.erase(iter
);
164 void GpuChannelManager::OnCreateViewCommandBuffer(
165 const gfx::GLSurfaceHandle
& window
,
168 const GPUCreateCommandBufferConfig
& init_params
) {
170 int32 route_id
= MSG_ROUTING_NONE
;
172 GpuChannelMap::const_iterator iter
= gpu_channels_
.find(client_id
);
173 if (iter
!= gpu_channels_
.end()) {
174 iter
->second
->CreateViewCommandBuffer(
175 window
, surface_id
, init_params
, &route_id
);
178 Send(new GpuHostMsg_CommandBufferCreated(route_id
));
181 void GpuChannelManager::CreateImage(
182 gfx::PluginWindowHandle window
, int32 client_id
, int32 image_id
) {
185 GpuChannelMap::const_iterator iter
= gpu_channels_
.find(client_id
);
186 if (iter
!= gpu_channels_
.end()) {
187 iter
->second
->CreateImage(window
, image_id
, &size
);
190 Send(new GpuHostMsg_ImageCreated(size
));
193 void GpuChannelManager::OnCreateImage(
194 gfx::PluginWindowHandle window
, int32 client_id
, int32 image_id
) {
197 if (image_operations_
.empty()) {
198 CreateImage(window
, client_id
, image_id
);
200 image_operations_
.push_back(
201 new ImageOperation(0, base::Bind(&GpuChannelManager::CreateImage
,
202 base::Unretained(this),
209 void GpuChannelManager::DeleteImage(int32 client_id
, int32 image_id
) {
210 GpuChannelMap::const_iterator iter
= gpu_channels_
.find(client_id
);
211 if (iter
!= gpu_channels_
.end()) {
212 iter
->second
->DeleteImage(image_id
);
216 void GpuChannelManager::OnDeleteImage(
217 int32 client_id
, int32 image_id
, int32 sync_point
) {
220 if (!sync_point
&& image_operations_
.empty()) {
221 DeleteImage(client_id
, image_id
);
223 image_operations_
.push_back(
224 new ImageOperation(sync_point
,
225 base::Bind(&GpuChannelManager::DeleteImage
,
226 base::Unretained(this),
230 sync_point_manager()->AddSyncPointCallback(
232 base::Bind(&GpuChannelManager::OnDeleteImageSyncPointRetired
,
233 base::Unretained(this),
234 image_operations_
.back()));
239 void GpuChannelManager::OnDeleteImageSyncPointRetired(
240 ImageOperation
* image_operation
) {
241 // Mark operation as no longer having a pending sync point.
242 image_operation
->sync_point
= 0;
244 // De-queue operations until we reach a pending sync point.
245 while (!image_operations_
.empty()) {
246 // Check if operation has a pending sync point.
247 if (image_operations_
.front()->sync_point
)
250 image_operations_
.front()->callback
.Run();
251 delete image_operations_
.front();
252 image_operations_
.pop_front();
256 void GpuChannelManager::OnLoadedShader(std::string program_proto
) {
258 program_cache()->LoadProgram(program_proto
);
261 bool GpuChannelManager::HandleMessagesScheduled() {
262 for (GpuChannelMap::iterator iter
= gpu_channels_
.begin();
263 iter
!= gpu_channels_
.end(); ++iter
) {
264 if (iter
->second
->handle_messages_scheduled())
270 uint64
GpuChannelManager::MessagesProcessed() {
271 uint64 messages_processed
= 0;
273 for (GpuChannelMap::iterator iter
= gpu_channels_
.begin();
274 iter
!= gpu_channels_
.end(); ++iter
) {
275 messages_processed
+= iter
->second
->messages_processed();
277 return messages_processed
;
280 void GpuChannelManager::LoseAllContexts() {
281 for (GpuChannelMap::iterator iter
= gpu_channels_
.begin();
282 iter
!= gpu_channels_
.end(); ++iter
) {
283 iter
->second
->MarkAllContextsLost();
285 base::MessageLoop::current()->PostTask(
287 base::Bind(&GpuChannelManager::OnLoseAllContexts
,
288 weak_factory_
.GetWeakPtr()));
291 void GpuChannelManager::OnLoseAllContexts() {
292 gpu_channels_
.clear();
295 gfx::GLSurface
* GpuChannelManager::GetDefaultOffscreenSurface() {
296 if (!default_offscreen_surface_
.get()) {
297 default_offscreen_surface_
=
298 gfx::GLSurface::CreateOffscreenGLSurface(gfx::Size(1, 1));
300 return default_offscreen_surface_
.get();
303 } // namespace content