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/browser/gpu/gpu_process_host_ui_shim.h"
10 #include "base/command_line.h"
11 #include "base/debug/trace_event.h"
12 #include "base/id_map.h"
13 #include "base/lazy_instance.h"
14 #include "base/strings/string_number_conversions.h"
15 #include "content/browser/gpu/gpu_data_manager_impl.h"
16 #include "content/browser/gpu/gpu_process_host.h"
17 #include "content/browser/gpu/gpu_surface_tracker.h"
18 #include "content/browser/renderer_host/render_process_host_impl.h"
19 #include "content/browser/renderer_host/render_view_host_impl.h"
20 #include "content/browser/renderer_host/render_widget_host_view_base.h"
21 #include "content/common/gpu/gpu_messages.h"
22 #include "content/public/browser/browser_thread.h"
23 #include "ui/gl/gl_switches.h"
29 // One of the linux specific headers defines this as a macro.
34 base::LazyInstance
<IDMap
<GpuProcessHostUIShim
> > g_hosts_by_id
=
35 LAZY_INSTANCE_INITIALIZER
;
37 void SendOnIOThreadTask(int host_id
, IPC::Message
* msg
) {
38 GpuProcessHost
* host
= GpuProcessHost::FromID(host_id
);
45 class ScopedSendOnIOThread
{
47 ScopedSendOnIOThread(int host_id
, IPC::Message
* msg
)
53 ~ScopedSendOnIOThread() {
55 BrowserThread::PostTask(BrowserThread::IO
,
57 base::Bind(&SendOnIOThreadTask
,
63 void Cancel() { cancelled_
= true; }
67 scoped_ptr
<IPC::Message
> msg_
;
71 RenderWidgetHostViewBase
* GetRenderWidgetHostViewFromSurfaceID(
73 int render_process_id
= 0;
74 int render_widget_id
= 0;
75 if (!GpuSurfaceTracker::Get()->GetRenderWidgetIDForSurface(
76 surface_id
, &render_process_id
, &render_widget_id
))
79 RenderWidgetHost
* host
=
80 RenderWidgetHost::FromID(render_process_id
, render_widget_id
);
81 return host
? static_cast<RenderWidgetHostViewBase
*>(host
->GetView()) : NULL
;
86 void RouteToGpuProcessHostUIShimTask(int host_id
, const IPC::Message
& msg
) {
87 GpuProcessHostUIShim
* ui_shim
= GpuProcessHostUIShim::FromID(host_id
);
89 ui_shim
->OnMessageReceived(msg
);
92 GpuProcessHostUIShim::GpuProcessHostUIShim(int host_id
)
94 g_hosts_by_id
.Pointer()->AddWithID(this, host_id_
);
98 GpuProcessHostUIShim
* GpuProcessHostUIShim::Create(int host_id
) {
99 DCHECK(!FromID(host_id
));
100 return new GpuProcessHostUIShim(host_id
);
104 void GpuProcessHostUIShim::Destroy(int host_id
, const std::string
& message
) {
105 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
107 GpuDataManagerImpl::GetInstance()->AddLogMessage(
108 logging::LOG_ERROR
, "GpuProcessHostUIShim",
111 delete FromID(host_id
);
115 void GpuProcessHostUIShim::DestroyAll() {
116 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
117 while (!g_hosts_by_id
.Pointer()->IsEmpty()) {
118 IDMap
<GpuProcessHostUIShim
>::iterator
it(g_hosts_by_id
.Pointer());
119 delete it
.GetCurrentValue();
124 GpuProcessHostUIShim
* GpuProcessHostUIShim::FromID(int host_id
) {
125 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
126 return g_hosts_by_id
.Pointer()->Lookup(host_id
);
130 GpuProcessHostUIShim
* GpuProcessHostUIShim::GetOneInstance() {
131 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
132 if (g_hosts_by_id
.Pointer()->IsEmpty())
134 IDMap
<GpuProcessHostUIShim
>::iterator
it(g_hosts_by_id
.Pointer());
135 return it
.GetCurrentValue();
138 bool GpuProcessHostUIShim::Send(IPC::Message
* msg
) {
139 DCHECK(CalledOnValidThread());
140 return BrowserThread::PostTask(BrowserThread::IO
,
142 base::Bind(&SendOnIOThreadTask
,
147 bool GpuProcessHostUIShim::OnMessageReceived(const IPC::Message
& message
) {
148 DCHECK(CalledOnValidThread());
150 if (message
.routing_id() != MSG_ROUTING_CONTROL
)
153 return OnControlMessageReceived(message
);
156 void GpuProcessHostUIShim::SimulateRemoveAllContext() {
157 Send(new GpuMsg_Clean());
160 void GpuProcessHostUIShim::SimulateCrash() {
161 Send(new GpuMsg_Crash());
164 void GpuProcessHostUIShim::SimulateHang() {
165 Send(new GpuMsg_Hang());
168 GpuProcessHostUIShim::~GpuProcessHostUIShim() {
169 DCHECK(CalledOnValidThread());
170 g_hosts_by_id
.Pointer()->Remove(host_id_
);
173 bool GpuProcessHostUIShim::OnControlMessageReceived(
174 const IPC::Message
& message
) {
175 DCHECK(CalledOnValidThread());
177 IPC_BEGIN_MESSAGE_MAP(GpuProcessHostUIShim
, message
)
178 IPC_MESSAGE_HANDLER(GpuHostMsg_OnLogMessage
,
181 IPC_MESSAGE_HANDLER(GpuHostMsg_AcceleratedSurfaceInitialized
,
182 OnAcceleratedSurfaceInitialized
)
183 IPC_MESSAGE_HANDLER(GpuHostMsg_AcceleratedSurfaceBuffersSwapped
,
184 OnAcceleratedSurfaceBuffersSwapped
)
185 IPC_MESSAGE_HANDLER(GpuHostMsg_AcceleratedSurfacePostSubBuffer
,
186 OnAcceleratedSurfacePostSubBuffer
)
187 IPC_MESSAGE_HANDLER(GpuHostMsg_AcceleratedSurfaceSuspend
,
188 OnAcceleratedSurfaceSuspend
)
189 IPC_MESSAGE_HANDLER(GpuHostMsg_GraphicsInfoCollected
,
190 OnGraphicsInfoCollected
)
191 IPC_MESSAGE_HANDLER(GpuHostMsg_AcceleratedSurfaceRelease
,
192 OnAcceleratedSurfaceRelease
)
193 IPC_MESSAGE_HANDLER(GpuHostMsg_VideoMemoryUsageStats
,
194 OnVideoMemoryUsageStatsReceived
);
195 IPC_MESSAGE_HANDLER(GpuHostMsg_UpdateVSyncParameters
,
196 OnUpdateVSyncParameters
)
197 IPC_MESSAGE_HANDLER(GpuHostMsg_FrameDrawn
, OnFrameDrawn
)
199 IPC_MESSAGE_UNHANDLED_ERROR()
200 IPC_END_MESSAGE_MAP()
205 void GpuProcessHostUIShim::OnUpdateVSyncParameters(int surface_id
,
206 base::TimeTicks timebase
,
207 base::TimeDelta interval
) {
209 int render_process_id
= 0;
210 int render_widget_id
= 0;
211 if (!GpuSurfaceTracker::Get()->GetRenderWidgetIDForSurface(
212 surface_id
, &render_process_id
, &render_widget_id
)) {
215 RenderWidgetHost
* rwh
=
216 RenderWidgetHost::FromID(render_process_id
, render_widget_id
);
219 RenderWidgetHostImpl::From(rwh
)->UpdateVSyncParameters(timebase
, interval
);
222 void GpuProcessHostUIShim::OnLogMessage(
224 const std::string
& header
,
225 const std::string
& message
) {
226 GpuDataManagerImpl::GetInstance()->AddLogMessage(
227 level
, header
, message
);
230 void GpuProcessHostUIShim::OnGraphicsInfoCollected(
231 const gpu::GPUInfo
& gpu_info
) {
232 // OnGraphicsInfoCollected is sent back after the GPU process successfully
234 TRACE_EVENT0("test_gpu", "OnGraphicsInfoCollected");
236 GpuDataManagerImpl::GetInstance()->UpdateGpuInfo(gpu_info
);
239 void GpuProcessHostUIShim::OnAcceleratedSurfaceInitialized(int32 surface_id
,
241 RenderWidgetHostViewBase
* view
=
242 GetRenderWidgetHostViewFromSurfaceID(surface_id
);
245 view
->AcceleratedSurfaceInitialized(host_id_
, route_id
);
248 void GpuProcessHostUIShim::OnAcceleratedSurfaceBuffersSwapped(
249 const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params
& params
) {
250 TRACE_EVENT0("renderer",
251 "GpuProcessHostUIShim::OnAcceleratedSurfaceBuffersSwapped");
252 if (!ui::LatencyInfo::Verify(params
.latency_info
,
253 "GpuHostMsg_AcceleratedSurfaceBuffersSwapped"))
255 AcceleratedSurfaceMsg_BufferPresented_Params ack_params
;
256 ack_params
.mailbox
= params
.mailbox
;
257 ack_params
.sync_point
= 0;
258 ScopedSendOnIOThread
delayed_send(
260 new AcceleratedSurfaceMsg_BufferPresented(params
.route_id
,
263 RenderWidgetHostViewBase
* view
= GetRenderWidgetHostViewFromSurfaceID(
268 delayed_send
.Cancel();
270 GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params view_params
= params
;
272 RenderWidgetHostImpl
* impl
=
273 RenderWidgetHostImpl::From(view
->GetRenderWidgetHost());
274 for (size_t i
= 0; i
< view_params
.latency_info
.size(); i
++)
275 impl
->AddLatencyInfoComponentIds(&view_params
.latency_info
[i
]);
277 // View must send ACK message after next composite.
278 view
->AcceleratedSurfaceBuffersSwapped(view_params
, host_id_
);
279 view
->DidReceiveRendererFrame();
282 void GpuProcessHostUIShim::OnFrameDrawn(
283 const std::vector
<ui::LatencyInfo
>& latency_info
) {
284 if (!ui::LatencyInfo::Verify(latency_info
,
285 "GpuProcessHostUIShim::OnFrameDrawn"))
287 RenderWidgetHostImpl::CompositorFrameDrawn(latency_info
);
290 void GpuProcessHostUIShim::OnAcceleratedSurfacePostSubBuffer(
291 const GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params
& params
) {
292 TRACE_EVENT0("renderer",
293 "GpuProcessHostUIShim::OnAcceleratedSurfacePostSubBuffer");
294 if (!ui::LatencyInfo::Verify(params
.latency_info
,
295 "GpuHostMsg_AcceleratedSurfacePostSubBuffer"))
297 AcceleratedSurfaceMsg_BufferPresented_Params ack_params
;
298 ack_params
.mailbox
= params
.mailbox
;
299 ack_params
.sync_point
= 0;
300 ScopedSendOnIOThread
delayed_send(
302 new AcceleratedSurfaceMsg_BufferPresented(params
.route_id
,
305 RenderWidgetHostViewBase
* view
=
306 GetRenderWidgetHostViewFromSurfaceID(params
.surface_id
);
310 delayed_send
.Cancel();
312 GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params view_params
= params
;
314 RenderWidgetHostImpl
* impl
=
315 RenderWidgetHostImpl::From(view
->GetRenderWidgetHost());
316 for (size_t i
= 0; i
< view_params
.latency_info
.size(); i
++)
317 impl
->AddLatencyInfoComponentIds(&view_params
.latency_info
[i
]);
319 // View must send ACK message after next composite.
320 view
->AcceleratedSurfacePostSubBuffer(view_params
, host_id_
);
321 view
->DidReceiveRendererFrame();
324 void GpuProcessHostUIShim::OnAcceleratedSurfaceSuspend(int32 surface_id
) {
325 TRACE_EVENT0("renderer",
326 "GpuProcessHostUIShim::OnAcceleratedSurfaceSuspend");
328 RenderWidgetHostViewBase
* view
=
329 GetRenderWidgetHostViewFromSurfaceID(surface_id
);
333 view
->AcceleratedSurfaceSuspend();
336 void GpuProcessHostUIShim::OnAcceleratedSurfaceRelease(
337 const GpuHostMsg_AcceleratedSurfaceRelease_Params
& params
) {
338 RenderWidgetHostViewBase
* view
= GetRenderWidgetHostViewFromSurfaceID(
342 view
->AcceleratedSurfaceRelease();
345 void GpuProcessHostUIShim::OnVideoMemoryUsageStatsReceived(
346 const GPUVideoMemoryUsageStats
& video_memory_usage_stats
) {
347 GpuDataManagerImpl::GetInstance()->UpdateVideoMemoryUsageStats(
348 video_memory_usage_stats
);
351 } // namespace content